"""Monitoring tools for HAProxy MCP Server.""" from typing import Annotated from pydantic import Field from ..exceptions import HaproxyError from ..validation import validate_backend_name from ..haproxy_client import haproxy_cmd from ..utils import parse_stat_csv def register_monitoring_tools(mcp): """Register monitoring tools with MCP server.""" @mcp.tool() def haproxy_stats() -> str: """Get HAProxy status and statistics. Returns: Key HAProxy metrics (name, version, uptime, connections, etc.) """ try: result = haproxy_cmd("show info") stats = {} for line in result.split("\n"): if ":" in line: key, value = line.split(":", 1) stats[key.strip()] = value.strip() important = ["Name", "Version", "Uptime_sec", "CurrConns", "MaxConn", "Run_queue", "Tasks"] output = [] for key in important: if key in stats: output.append(f"• {key}: {stats[key]}") return "\n".join(output) if output else result except HaproxyError as e: return f"Error: {e}" @mcp.tool() def haproxy_backends() -> str: """List all HAProxy backends. Returns: List of all configured backend names """ try: result = haproxy_cmd("show backend") backends = [line for line in result.split("\n") if line and not line.startswith("#")] return "Backends:\n" + "\n".join(f"• {b}" for b in backends) except HaproxyError as e: return f"Error: {e}" @mcp.tool() def haproxy_list_frontends() -> str: """List all HAProxy frontends with their status. Returns: List of frontends with status and session counts """ try: result = haproxy_cmd("show stat") frontends = [] for stat in parse_stat_csv(result): if stat["svname"] == "FRONTEND": frontends.append( f"• {stat['pxname']}: {stat['status']} (sessions: {stat['scur']})" ) if not frontends: return "No frontends found" return "Frontends:\n" + "\n".join(frontends) except HaproxyError as e: return f"Error: {e}" @mcp.tool() def haproxy_get_connections( backend: Annotated[str, Field(default="", description="Optional: Backend name to filter (e.g., 'pool_1'). Empty = all backends")] = "" ) -> str: """Get active connection counts per server for monitoring traffic distribution.""" if backend and not validate_backend_name(backend): return "Error: Invalid backend name (use alphanumeric, underscore, hyphen only)" try: result = haproxy_cmd("show stat") connections = [] for stat in parse_stat_csv(result): if backend and stat["pxname"] != backend: continue if stat["svname"] in ["FRONTEND", "BACKEND"]: connections.append( f"• {stat['pxname']} ({stat['svname']}): {stat['scur']} current, {stat['smax']} max" ) elif stat["svname"]: connections.append(f" - {stat['svname']}: {stat['scur']} connections") return "\n".join(connections) if connections else "No connection data" except HaproxyError as e: return f"Error: {e}"