diff --git a/apps/api/src/plugins/mcp/mcp_bridge.py b/apps/api/src/plugins/mcp/mcp_bridge.py index c59a2d57..665d9e21 100644 --- a/apps/api/src/plugins/mcp/mcp_bridge.py +++ b/apps/api/src/plugins/mcp/mcp_bridge.py @@ -200,16 +200,21 @@ class MCPBridge: self._tool_cache: dict[str, list[MCPTool]] = {} self._http_client = httpx.AsyncClient(timeout=30.0) - # 註冊 Mock Servers (Phase 3: 先驗證介面) - self._register_mock_servers() + # 註冊 MCP Servers (Phase 13.2: 整合真實服務) + self._register_servers() - def _register_mock_servers(self) -> None: - """註冊 Mock MCP Servers (開發測試用)""" + def _register_servers(self) -> None: + """註冊 MCP Servers""" self._servers["kubernetes"] = MCPServer( name="kubernetes", transport=MCPTransport.HTTP, endpoint="http://localhost:8081/mcp", ) + self._servers["signoz"] = MCPServer( + name="signoz", + transport=MCPTransport.HTTP, + endpoint="http://192.168.0.188:3301", # SignOz Query Service + ) self._servers["filesystem"] = MCPServer( name="filesystem", transport=MCPTransport.STDIO, @@ -319,6 +324,47 @@ class MCPBridge: server_name=server.name, ), ], + "signoz": [ + MCPTool( + name="gold_metrics", + description="Get Gold Metrics (RPS, Error Rate, P99 Latency) for a service", + input_schema={ + "type": "object", + "properties": { + "service_name": {"type": "string", "description": "Service name (e.g., api-gateway)"}, + "namespace": {"type": "string", "description": "K8s namespace (default: awoooi-prod)"}, + "time_window_minutes": {"type": "integer", "description": "Time window in minutes (default: 10)"}, + }, + "required": ["service_name"], + }, + server_name=server.name, + ), + MCPTool( + name="trace_url", + description="Generate SignOz trace URL for debugging a service", + input_schema={ + "type": "object", + "properties": { + "service_name": {"type": "string", "description": "Service name"}, + "window_minutes": {"type": "integer", "description": "Time window ± minutes (default: 5)"}, + }, + "required": ["service_name"], + }, + server_name=server.name, + ), + MCPTool( + name="system_metrics", + description="Get system metrics (CPU, Disk I/O) from SignOz", + input_schema={ + "type": "object", + "properties": { + "host": {"type": "string", "description": "Host IP (default: 192.168.0.188)"}, + "time_window_minutes": {"type": "integer", "description": "Time window in minutes (default: 5)"}, + }, + }, + server_name=server.name, + ), + ], "database": [ MCPTool( name="query", @@ -568,6 +614,82 @@ class MCPBridge: else: return {"error": f"Unknown kubernetes tool: {tool_name}"} + # ============================================= + # SignOz: 監控指標查詢 (Phase 13.2 #79) + # ============================================= + elif server.name == "signoz": + from src.services.signoz_client import get_signoz_client + + signoz = get_signoz_client() + + if tool_name == "gold_metrics": + # 取得 Gold Metrics (RPS, Error Rate, P99) + service_name = parameters.get("service_name", "") + if not service_name: + return {"error": "Missing 'service_name' parameter"} + + namespace = parameters.get("namespace", "awoooi-prod") + time_window = parameters.get("time_window_minutes", 10) + + metrics = await signoz.get_gold_metrics( + service_name=service_name, + namespace=namespace, + time_window_minutes=time_window, + ) + + return { + "service_name": metrics.service_name, + "namespace": metrics.namespace, + "rps": round(metrics.rps, 2), + "rps_trend": metrics.rps_trend, + "error_rate": round(metrics.error_rate, 2), + "error_count": metrics.error_count, + "total_requests": metrics.total_requests, + "p50_latency_ms": round(metrics.p50_latency_ms, 1), + "p95_latency_ms": round(metrics.p95_latency_ms, 1), + "p99_latency_ms": round(metrics.p99_latency_ms, 1), + "latency_trend": metrics.latency_trend, + "summary": metrics.to_summary(), + } + + elif tool_name == "trace_url": + # 生成 SignOz Trace URL + service_name = parameters.get("service_name", "") + if not service_name: + return {"error": "Missing 'service_name' parameter"} + + window_minutes = parameters.get("window_minutes", 5) + url = signoz.generate_trace_url( + service_name=service_name, + window_minutes=window_minutes, + ) + + return { + "service_name": service_name, + "trace_url": url, + "window_minutes": window_minutes, + } + + elif tool_name == "system_metrics": + # 取得系統指標 (CPU/Disk) + host = parameters.get("host", "192.168.0.188") + time_window = parameters.get("time_window_minutes", 5) + + metrics = await signoz.get_system_metrics( + _host=host, + time_window_minutes=time_window, + ) + + return { + "host": host, + "cpu": metrics.get("cpu", {}), + "disk": metrics.get("disk", {}), + "time_range": metrics.get("time_range", {}), + } + + else: + return {"error": f"Unknown signoz tool: {tool_name}"} + # ============================================= # Database: 查詢 incident/approval 歷史 (Phase 13.2 #81) # =============================================