""" MCP tool for listing Loki series metadata. This tool allows authorized AI agents and developers to discover series (label combinations) that match certain patterns in Loki. Returns JSON in Loki API format: {"status": "success", "data": [{"label1": "value1", "label2": "value2"}, ...]}. """ import json from typing import Any from pydantic import ValidationError as PydanticValidationError from src.models.loki_queries import LokiSeriesRequest from src.services.auth import get_valid_server_auth from src.services.loki_resolve import get_loki_client_for_cluster from src.tools.query_range import mcp from src.utils.errors import ( AuthorizationError, AuthServiceError, LokiAPIError, LokiTimeoutError, NetworkError, ValidationError, ) from src.utils.tool_response import format_tool_error, tool_text_response @mcp.tool() async def list_loki_series( match: list[str], cluster_id: str, env: str, deploy_type: str, start: str | None = None, end: str | None = None, ) -> list[dict[str, Any]]: """ List series metadata (label combinations) that match certain patterns in Loki. Returns JSON in the same format as Loki /loki/api/v1/series: {"status": "success", "data": [{"label1": "value1", "label2": "value2"}, ...]}. Args: match: List of LogQL query patterns to match series (e.g., ['{app="mysql"}', '{namespace="prod"}']) cluster_id: Cluster identifier. env: Environment name (e.g. prod, staging, dev). deploy_type: Deploy type (dedicated, premium, resource_pool, starter, essential). start: Optional start timestamp in RFC3339 format for time range end: Optional end timestamp in RFC3339 format for time range Returns: List containing a single dict with 'type': 'text' and 'text': Loki-format JSON Raises: Various errors for authorization, validation, network, and timeout issues Examples: # List series for a single pattern match=['{app="mysql"}'] # List series for multiple patterns match=['{app="mysql"}', '{app="tidb"}'] # List series in a specific time range match=['{namespace="production"}'] start='2024-01-01T00:00:00Z' end='2024-01-01T23:59:59Z' """ try: await get_valid_server_auth() try: request = LokiSeriesRequest( match=match, cluster_id=cluster_id.strip(), env=env.strip(), deploy_type=deploy_type.strip(), start=start, end=end, ) except (ValueError, PydanticValidationError) as e: raise ValidationError(f"Invalid Loki series request parameters: {str(e)}") from e client, region = await get_loki_client_for_cluster( cluster_id=request.cluster_id, env=request.env, deploy_type=request.deploy_type, timeout=15.0, ) match_query = ",".join(request.match) series = await client.list_series( match=match_query, start=request.start, end=request.end, ) response = {"status": "success", "data": series} return tool_text_response(json.dumps(response, ensure_ascii=False)) except ( AuthServiceError, AuthorizationError, ValidationError, NetworkError, LokiTimeoutError, LokiAPIError, ) as e: return tool_text_response(format_tool_error(e)) except Exception as e: return tool_text_response(format_tool_error(e))