Skip to main content
Glama
DrDroidLab

Grafana MCP Server

grafana_loki_query

Query Grafana Loki log data with time-based filtering and structured matchers to retrieve specific log entries for analysis.

Instructions

Queries Grafana Loki for log data. Fetches logs for a specified duration (e.g., '5m', '1h', '2d'), converts relative time to absolute timestamps. Note: Loki queries require at least one non-empty matcher. Use patterns like '{job=~".+"}' instead of '{job=~".*"}' or '{}' to avoid syntax errors.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
datasource_uidYesLoki datasource UID
queryYesLoki query string (e.g., '{job=~".+"}' or '{app="myapp"}')
durationNoTime duration (e.g., '5m', '1h', '2d') - overrides start_time/end_time if provided
start_timeNoStart time in RFC3339 or relative string (e.g., 'now-2h', '2023-01-01T00:00:00Z')
end_timeNoEnd time in RFC3339 or relative string (e.g., 'now-2h', '2023-01-01T00:00:00Z')
limitNoMaximum number of log entries to return

Implementation Reference

  • The `grafana_loki_query` function in the GrafanaProcessor class executes Loki queries against a specified datasource using the Grafana API.
    def grafana_loki_query(
        self,
        datasource_uid: str,
        query: str,
        duration: Optional[str] = None,
        start_time: Optional[str] = None,
        end_time: Optional[str] = None,
        limit: int = 100,
    ) -> dict[str, Any]:
        """
        Queries Grafana Loki for log data.
    
        Args:
            query: Loki query string
            duration: Time duration (e.g., '5m', '1h', '2d') - overrides start_time/end_time if provided
            start_time: Start time in RFC3339 or relative string (e.g., 'now-2h', '2023-01-01T00:00:00Z')
            end_time: End time in RFC3339 or relative string (e.g., 'now-2h', '2023-01-01T00:00:00Z')
            limit: Maximum number of log entries to return
    
        Returns:
            Dict containing log data from Loki datasource
        """
        try:
            # Use standardized time range logic
            start_dt, end_dt = self._get_time_range(start_time, end_time, duration, default_hours=1)
    
            # Convert to milliseconds since epoch (Grafana format)
            start_ms = int(start_dt.timestamp() * 1000)
            end_ms = int(end_dt.timestamp() * 1000)
    
            payload = {
                "queries": [
                    {
                        "refId": "A",
                        "expr": query,
                        "datasource": {"type": "loki", "uid": datasource_uid},
                        "maxLines": limit,
                    }
                ],
                "from": str(start_ms),
                "to": str(end_ms),
            }
    
            url = f"{self.__host}/api/ds/query"
            logger.info(f"Executing Loki query: {query} from {start_dt.isoformat()} to {end_dt.isoformat()}")
    
            response = requests.post(
                url,
                headers=self.headers,
                json=payload,
                verify=self.__ssl_verify,
                timeout=30,
            )
    
            if response.status_code == 200:
                data = response.json()
                return {
                    "status": "success",
                    "query": query,
                    "start_time": start_dt.isoformat(),
                    "end_time": end_dt.isoformat(),
                    "duration": duration,
                    "limit": limit,
                    "results": data,
                }
            else:
                raise Exception(f"Loki query failed. Status: {response.status_code}, Response: {response.text}")
    
        except Exception as e:
            logger.error(f"Error executing Loki query: {e!s}")
            raise e
  • The tool 'grafana_loki_query' is defined in the tools list within the MCP server setup.
    "name": "grafana_loki_query",
    "description": "Queries Grafana Loki for log data. Fetches logs for a specified duration "
  • The tool 'grafana_loki_query' is registered in the tool handler mapping in the MCP server.
    "grafana_loki_query": grafana_loki_query,
  • The tool handler function in `mcp_server.py` that calls the underlying processor method.
    def grafana_loki_query(datasource_uid, query, duration=None, start_time=None, end_time=None, limit=100):
        """Query Grafana Loki for log data"""
        try:
            grafana_processor = current_app.config.get("grafana_processor")
            if not grafana_processor:
                return {
                    "status": "error",
                    "message": "Grafana processor not initialized. Check configuration.",
                }
    
            result = grafana_processor.grafana_loki_query(datasource_uid, query, duration, start_time, end_time, limit)
            return result
        except Exception as e:
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure. It effectively describes key behavioral traits: the tool converts relative time to absolute timestamps, enforces query syntax requirements, and provides examples to avoid errors. However, it doesn't mention rate limits, authentication needs, or pagination behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is efficiently structured in three sentences: purpose statement, behavioral detail, and critical usage note. Every sentence earns its place by providing essential information without redundancy or fluff.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a query tool with no annotations and no output schema, the description provides strong contextual completeness: it covers purpose, usage constraints, and behavioral details. The main gap is the lack of information about return format or error handling, which would be helpful given the absence of an output schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents all parameters thoroughly. The description adds minimal parameter semantics beyond the schema—it mentions duration examples and query patterns, but doesn't provide additional meaning for parameters like datasource_uid or limit. Baseline 3 is appropriate when the schema does the heavy lifting.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose with specific verbs ('queries', 'fetches') and resources ('Grafana Loki', 'log data'), and distinguishes it from sibling tools by focusing on Loki querying rather than dashboard operations or PromQL queries.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit usage guidance: it specifies when to use this tool (for querying Loki log data), includes a critical constraint ('requires at least one non-empty matcher'), and offers concrete alternatives to avoid syntax errors (e.g., '{job=~".+"}' instead of '{job=~".*"}').

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/DrDroidLab/grafana-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server