Skip to content

miru

Rust · MCP

An MCP server that lets LLM agents read your Grafana Loki logs and Prometheus metrics.

Why I built it

Something breaks, I open Grafana, write the LogQL again, download the logs, paste them into Claude Code and ask what happened. I did that a lot, and the downloading and pasting got old. So I built miru, and now the agent queries Loki and Prometheus itself.

How it's put together

miru is an MCP server that talks over stdio. It runs inside any MCP host, like Claude Code, Codex or Gemini CLI, and doesn't need its own daemon. Tools are registered per backend, so if you only point it at Loki you only get the log tools.

Both backends share the same transport and auth code. They're both HTTP APIs behind the same Grafana credentials, so keeping them apart would have meant writing auth and error handling twice.

Things I had to handle

Two kinds of endpoint

You can reach Loki directly or through Grafana's datasource proxy, and the URLs are different. The Grafana docs mention this, so I handled both from the start. miru detects which one it's talking to, so you don't have to configure it.

Result size

A PromQL range query on a busy service returns more samples than a model can read, and they push the rest of the conversation out of its context. miru summarizes each series and picks the step size based on the time range, so the response stays small enough to be useful.

What it does

miru only reads. It lists services and metrics with their metadata, searches logs by level, text or regex, and aggregates metrics over a time range. It never writes to Loki or Prometheus.

Auth can be bearer, basic or an environment variable. Tokens come from the environment, so there are no secrets in the config file.

  1. 1 Generate a Grafana service account token.
  2. 2 Write ~/.config/miru/config.toml with the backend labels.
  3. 3 Register miru with your MCP host. Claude and Gemini use JSON, Codex uses TOML.

Why Rust

Most MCP servers are written in TypeScript. An MCP server runs on your own machine, started by your MCP host, so installing it is part of using it. cargo install miru-mcp gives you a single binary, with no Node runtime to install or keep updated.

Rust also makes it easier to keep two backends behind one interface, but the single binary is the main reason.