add health check tool
This commit is contained in:
+144
-2
@@ -1003,7 +1003,7 @@ async def search_yargitay_detailed(
|
||||
logger.info(f"Tool 'search_yargitay_detailed' called: {search_query.model_dump_json(exclude_none=True, indent=2)}")
|
||||
try:
|
||||
api_response = await yargitay_client_instance.search_detailed_decisions(search_query)
|
||||
if api_response.data:
|
||||
if api_response and api_response.data and api_response.data.data:
|
||||
# Convert to clean decision entries without arananKelime field
|
||||
clean_decisions = [
|
||||
CleanYargitayDecisionEntry(
|
||||
@@ -1018,7 +1018,7 @@ async def search_yargitay_detailed(
|
||||
]
|
||||
return CompactYargitaySearchResult(
|
||||
decisions=clean_decisions,
|
||||
total_records=api_response.data.recordsTotal,
|
||||
total_records=api_response.data.recordsTotal if api_response.data else 0,
|
||||
requested_page=search_query.pageNumber,
|
||||
page_size=search_query.pageSize)
|
||||
logger.warning("API response for Yargitay search did not contain expected data structure.")
|
||||
@@ -2321,6 +2321,148 @@ def perform_cleanup():
|
||||
|
||||
atexit.register(perform_cleanup)
|
||||
|
||||
# --- Health Check Tools ---
|
||||
@app.tool(
|
||||
description="Check if Turkish government legal database servers are operational",
|
||||
annotations={
|
||||
"readOnlyHint": True,
|
||||
"idempotentHint": True
|
||||
}
|
||||
)
|
||||
async def check_government_servers_health() -> Dict[str, Any]:
|
||||
"""Check health status of Turkish government legal database servers."""
|
||||
logger.info("Health check tool called for government servers")
|
||||
|
||||
health_results = {}
|
||||
|
||||
# Check Yargıtay server
|
||||
try:
|
||||
yargitay_payload = {
|
||||
"data": {
|
||||
"aranan": "karar",
|
||||
"arananKelime": "karar",
|
||||
"pageSize": 10,
|
||||
"pageNumber": 1
|
||||
}
|
||||
}
|
||||
|
||||
async with httpx.AsyncClient(
|
||||
headers={
|
||||
"Accept": "*/*",
|
||||
"Accept-Language": "tr-TR,tr;q=0.9,en-US;q=0.8,en;q=0.7",
|
||||
"Connection": "keep-alive",
|
||||
"Content-Type": "application/json; charset=UTF-8",
|
||||
"Origin": "https://karararama.yargitay.gov.tr",
|
||||
"Referer": "https://karararama.yargitay.gov.tr/",
|
||||
"Sec-Fetch-Dest": "empty",
|
||||
"Sec-Fetch-Mode": "cors",
|
||||
"Sec-Fetch-Site": "same-origin",
|
||||
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36",
|
||||
"X-Requested-With": "XMLHttpRequest"
|
||||
},
|
||||
timeout=30.0,
|
||||
verify=False
|
||||
) as client:
|
||||
response = await client.post(
|
||||
"https://karararama.yargitay.gov.tr/aramalist",
|
||||
json=yargitay_payload
|
||||
)
|
||||
|
||||
if response.status_code == 200:
|
||||
response_data = response.json()
|
||||
records_total = response_data.get("data", {}).get("recordsTotal", 0)
|
||||
|
||||
if records_total > 0:
|
||||
health_results["yargitay"] = {
|
||||
"status": "healthy",
|
||||
"records_total": records_total,
|
||||
"response_time_ms": response.elapsed.total_seconds() * 1000
|
||||
}
|
||||
else:
|
||||
health_results["yargitay"] = {
|
||||
"status": "unhealthy",
|
||||
"reason": "recordsTotal is 0 or missing",
|
||||
"response_time_ms": response.elapsed.total_seconds() * 1000
|
||||
}
|
||||
else:
|
||||
health_results["yargitay"] = {
|
||||
"status": "unhealthy",
|
||||
"reason": f"HTTP {response.status_code}",
|
||||
"response_time_ms": response.elapsed.total_seconds() * 1000
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
health_results["yargitay"] = {
|
||||
"status": "unhealthy",
|
||||
"reason": f"Connection error: {str(e)}"
|
||||
}
|
||||
|
||||
# Check Bedesten API server
|
||||
try:
|
||||
bedesten_payload = {
|
||||
"phrase": "karar",
|
||||
"itemTypeList": ["YARGITAYKARARI"],
|
||||
"pageSize": 5,
|
||||
"page": 1
|
||||
}
|
||||
|
||||
async with httpx.AsyncClient(
|
||||
headers={
|
||||
"Content-Type": "application/json",
|
||||
"Accept": "application/json",
|
||||
"User-Agent": "Mozilla/5.0 Health Check"
|
||||
},
|
||||
timeout=30.0,
|
||||
verify=False
|
||||
) as client:
|
||||
response = await client.post(
|
||||
"https://bedesten.adalet.gov.tr/api/search",
|
||||
json=bedesten_payload
|
||||
)
|
||||
|
||||
if response.status_code == 200:
|
||||
response_data = response.json()
|
||||
total_found = response_data.get("totalFound", 0)
|
||||
|
||||
if total_found > 0:
|
||||
health_results["bedesten"] = {
|
||||
"status": "healthy",
|
||||
"total_found": total_found,
|
||||
"response_time_ms": response.elapsed.total_seconds() * 1000
|
||||
}
|
||||
else:
|
||||
health_results["bedesten"] = {
|
||||
"status": "unhealthy",
|
||||
"reason": "totalFound is 0 or missing",
|
||||
"response_time_ms": response.elapsed.total_seconds() * 1000
|
||||
}
|
||||
else:
|
||||
health_results["bedesten"] = {
|
||||
"status": "unhealthy",
|
||||
"reason": f"HTTP {response.status_code}",
|
||||
"response_time_ms": response.elapsed.total_seconds() * 1000
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
health_results["bedesten"] = {
|
||||
"status": "unhealthy",
|
||||
"reason": f"Connection error: {str(e)}"
|
||||
}
|
||||
|
||||
# Overall health assessment
|
||||
healthy_servers = sum(1 for server in health_results.values() if server["status"] == "healthy")
|
||||
total_servers = len(health_results)
|
||||
|
||||
overall_status = "healthy" if healthy_servers == total_servers else "degraded" if healthy_servers > 0 else "unhealthy"
|
||||
|
||||
return {
|
||||
"overall_status": overall_status,
|
||||
"healthy_servers": healthy_servers,
|
||||
"total_servers": total_servers,
|
||||
"servers": health_results,
|
||||
"check_timestamp": f"{__import__('datetime').datetime.now().isoformat()}"
|
||||
}
|
||||
|
||||
# --- MCP Tools for KVKK ---
|
||||
@app.tool(
|
||||
description="Search KVKK decisions using Brave Search API for data protection authority decisions. Before using, read docs://tools/kvkk",
|
||||
|
||||
@@ -65,6 +65,19 @@ class YargitayOfficialApiClient:
|
||||
response.raise_for_status() # Raise an exception for HTTP 4xx or 5xx status codes
|
||||
response_json_data = response.json()
|
||||
|
||||
logger.debug(f"YargitayOfficialApiClient: Raw API response: {response_json_data}")
|
||||
|
||||
# Handle None or empty data response from API
|
||||
if response_json_data is None:
|
||||
logger.warning("YargitayOfficialApiClient: API returned None response")
|
||||
response_json_data = {"data": {"data": [], "recordsTotal": 0, "recordsFiltered": 0}}
|
||||
elif not isinstance(response_json_data, dict):
|
||||
logger.warning(f"YargitayOfficialApiClient: API returned unexpected response type: {type(response_json_data)}")
|
||||
response_json_data = {"data": {"data": [], "recordsTotal": 0, "recordsFiltered": 0}}
|
||||
elif response_json_data.get("data") is None:
|
||||
logger.warning("YargitayOfficialApiClient: API response data field is None")
|
||||
response_json_data["data"] = {"data": [], "recordsTotal": 0, "recordsFiltered": 0}
|
||||
|
||||
# Validate and parse the response using Pydantic models
|
||||
api_response = YargitayApiSearchResponse(**response_json_data)
|
||||
|
||||
|
||||
@@ -74,14 +74,14 @@ class YargitayApiDecisionEntry(BaseModel):
|
||||
|
||||
class YargitayApiResponseInnerData(BaseModel):
|
||||
"""Model for the inner 'data' object in the Yargitay API search response."""
|
||||
data: List[YargitayApiDecisionEntry]
|
||||
data: List[YargitayApiDecisionEntry] = Field(default_factory=list)
|
||||
# draw: Optional[int] = None # Typically used by DataTables, not essential for MCP
|
||||
recordsTotal: int # Total number of records matching the query
|
||||
recordsFiltered: int # Total number of records after filtering (usually same as recordsTotal)
|
||||
recordsTotal: int = Field(default=0) # Total number of records matching the query
|
||||
recordsFiltered: int = Field(default=0) # Total number of records after filtering (usually same as recordsTotal)
|
||||
|
||||
class YargitayApiSearchResponse(BaseModel):
|
||||
"""Model for the complete search response from the Yargitay API."""
|
||||
data: YargitayApiResponseInnerData
|
||||
data: Optional[YargitayApiResponseInnerData] = Field(default_factory=lambda: YargitayApiResponseInnerData())
|
||||
# metadata: Optional[Dict[str, Any]] = None # Optional metadata from API
|
||||
|
||||
class YargitayDocumentMarkdown(BaseModel):
|
||||
|
||||
Reference in New Issue
Block a user