We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/rajmohanram/ceph-mcp-server'
If you have feedback or need assistance with the MCP directory API, please join our Discord server
"""
Health Domain Handlers
This module contains all MCP request handlers related to cluster health.
"""
from datetime import datetime
from typing import Any
from ceph_mcp.handlers.base import BaseHandler
from ceph_mcp.models.base import MCPResponse
class HealthHandlers(BaseHandler):
"""
Handlers for health-related MCP operations.
This class provides all health-related functionality for the MCP server,
including retrieving health summaries, detailed checks, recommendations.
"""
def __init__(self) -> None:
super().__init__(domain="health")
async def _handle_operation(
self, operation: str, params: dict[str, Any]
) -> MCPResponse:
"""Route health operations to appropriate methods."""
operation_map = {
"get_health_summary": self.get_health_summary,
"get_health_details": self.get_health_details,
"get_health_recommendations": self.get_health_recommendations,
"get_cluster_capacity": self.get_cluster_capacity,
}
if operation not in operation_map:
return self.create_error_response(
message=f"Unknown health operation: {operation}",
error_code="UNKNOWN_OPERATION",
)
return await operation_map[operation](params)
async def get_health_summary(self, params: dict[str, Any]) -> MCPResponse:
"""
Get health summary of the Ceph cluster.
This provides the essential health information that administrators
need for daily cluster management.
"""
# Validate required parameters
self.validate_required_params(params, [])
# Use global client instead of creating new one
client = await self.get_global_client()
# Get raw health data
health = await client.health.get_cluster_health()
# Format response data
summary_data = {
"executive_summary": health.get_executive_summary(),
"health_score": health.get_health_score(),
"status": health.status.value,
"cluster_fsid": health.cluster_fsid,
"is_healthy": health.is_healthy(),
"has_warnings": health.has_warnings(),
"has_errors": health.has_errors(),
"description": health.overall_status_description,
"checks_summary": {
"total": len(health.checks),
"critical": len(health.get_critical_checks()),
"warnings": len(health.get_warning_checks()),
},
"recommendations": health.get_recommendations(),
"timestamp": health.collected_at.isoformat(),
}
# Generate appropriate message
if health.is_healthy():
message = f"Cluster is healthy (Score: {health.get_health_score()}/100)"
elif health.has_errors():
message = f"Cluster has {len(health.get_critical_checks())} critical issue(s) requiring immediate attention"
else:
message = f"Cluster has {len(health.get_warning_checks())} warning(s) that should be investigated"
response = self.create_success_response(data=summary_data, message=message)
return response
async def get_health_details(self, params: dict[str, Any]) -> MCPResponse:
"""
Get detailed health check information for troubleshooting.
This provides in-depth information about specific health issues
for detailed diagnosis and resolution.
"""
# Optional filtering parameters
severity_filter = self.get_optional_param(params, "severity", None)
# Use global client instead of creating new one
client = await self.get_global_client()
health = await client.health.get_cluster_health()
# Sort checks by priority
checks_by_priority = health.get_checks_by_priority()
# Apply severity filter if specified
if severity_filter:
checks_by_priority = [
check
for check in checks_by_priority
if check.severity.value == severity_filter
]
# Format detailed response
health_details = {
"overall_status": health.status.value,
"health_score": health.get_health_score(),
"description": health.overall_status_description,
"checks": [
{
"type": check.type,
"severity": check.severity.value,
"summary": check.summary,
"detail": check.details,
"count": check.count,
"is_critical": check.is_critical(),
"is_warning": check.is_warning(),
"priority_score": check.get_priority_score(),
}
for check in checks_by_priority
],
"check_statistics": {
"total_checks": len(checks_by_priority),
"critical_count": len(
[check for check in checks_by_priority if check.is_critical()]
),
"warning_count": len(
[check for check in checks_by_priority if check.is_warning()]
),
"filtered_by_severity": severity_filter,
},
"recommendations": health.get_recommendations(),
"timestamp": datetime.now().isoformat(),
}
# Generate message based on findings
if not checks_by_priority:
if severity_filter:
message = f"No health checks found with severity '{severity_filter}'"
else:
message = "Cluster is healthy with no active health checks"
else:
critical_count = len(
[check for check in checks_by_priority if check.is_critical()]
)
warning_count = len(
[check for check in checks_by_priority if check.is_warning()]
)
parts = []
if critical_count > 0:
parts.append(f"{critical_count} critical issue(s)")
if warning_count > 0:
parts.append(f"{warning_count} warning(s)")
message = f"Found {' and '.join(parts)} requiring attention"
return self.create_success_response(data=health_details, message=message)
async def get_health_recommendations(self, params: dict[str, Any]) -> MCPResponse:
"""
Get specific health recommendations and action items.
This focuses on providing actionable guidance for cluster management.
"""
priority_only = self.get_optional_param(params, "priority_only", False)
max_recommendations = self.get_optional_param(params, "max_recommendations", 10)
# Use global client instead of creating new one
client = await self.get_global_client()
health = await client.health.get_cluster_health()
# Get comprehensive recommendations
recommendations = health.get_recommendations()
# If priority_only is True, filter to most important items
if priority_only:
# Focus on critical issues first
critical_checks = health.get_critical_checks()
if critical_checks:
recommendations = [
"🚨 Critical issues require immediate attention:",
*[f" - {check.summary}" for check in critical_checks[:3]],
]
else:
warning_checks = health.get_warning_checks()
if warning_checks:
recommendations = [
"⚠️ Address these warnings when possible:",
*[f" - {check.summary}" for check in warning_checks[:3]],
]
else:
recommendations = [
"✅ No immediate action required - cluster is healthy"
]
# Limit number of recommendations
recommendations = recommendations[:max_recommendations]
recommendation_data = {
"recommendations": recommendations,
"health_score": health.get_health_score(),
"priority_filter_applied": priority_only,
"max_items": max_recommendations,
"total_available": len(health.get_recommendations()),
"cluster_status": health.status.value,
"generated_at": datetime.now().isoformat(),
}
message = f"Generated {len(recommendations)} health recommendations"
if priority_only:
message += " (priority items only)"
return self.create_success_response(data=recommendation_data, message=message)
async def get_cluster_capacity(self, params: dict[str, Any]) -> MCPResponse:
"""
Get cluster capacity summary.
This provides essential cluster capacity information including
total objects, capacity in GB, and pool usage statistics.
"""
# Validate required parameters
self.validate_required_params(params, [])
# Use global client instead of creating new one
client = await self.get_global_client()
# Get cluster capacity data
capacity = await client.health.get_cluster_capacity()
# Format response data
capacity_data = {
"cluster_capacity": {
"total_objects": capacity.total_objects,
"total_capacity_gb": capacity.get_total_capacity_gb(),
"used_capacity_gb": capacity.get_used_capacity_gb(),
"available_capacity_gb": capacity.get_available_capacity_gb(),
"pool_bytes_used_gb": capacity.get_pool_bytes_used_gb(),
"usage_percentage": capacity.get_usage_percentage(),
"average_object_size_kb": capacity.get_average_object_size_kb(),
},
"raw_data": {
"total_avail_bytes": capacity.total_avail_bytes,
"total_bytes": capacity.total_bytes,
"total_used_raw_bytes": capacity.total_used_raw_bytes,
"total_pool_bytes_used": capacity.total_pool_bytes_used,
"average_object_size": capacity.average_object_size,
},
"summary": capacity.get_capacity_summary(),
"timestamp": datetime.now().isoformat(),
}
# Generate descriptive message
message = f"Cluster capacity: {capacity.get_capacity_summary()} with {capacity.total_objects:,} objects"
return self.create_success_response(data=capacity_data, message=message)