Skip to main content
Glama
ThainaJardim

observability-mcp

by ThainaJardim
README.md
# observability-mcp

MCP (Model Context Protocol) servers that let AI assistants query your
observability stack — **Grafana/Loki** for logs and **Thanos/Prometheus** for
metrics — directly from Cursor, Claude Desktop, or any MCP-compatible client.

## Packages

| Package | Entry-point | What it does |
|---------|-------------|--------------|
| `grafana_mcp` | `grafana-mcp` | Query Loki logs via Grafana datasource proxy |
| `thanos_mcp` | `thanos-mcp` | Query Prometheus/Thanos metrics (PromQL) |
| `observability_mcp` | `observability-mcp` | Combined server — all tools in one connection |

## Requirements

- Python 3.10+
- Access to a running Grafana instance (for `grafana_mcp`)
- Access to a Thanos or Prometheus instance (for `thanos_mcp`)

## Installation

### From GitHub (recommended)

Install directly from the repo without cloning:

```bash
pip install "observability-mcp @ git+https://github.com/ThainaJardim/observability-mcp.git"

# With browser-cookie support for Grafana SSO:
pip install "observability-mcp[browser-cookie] @ git+https://github.com/ThainaJardim/observability-mcp.git"
```

After installation, the `grafana-mcp`, `thanos-mcp`, and `observability-mcp` commands are available.

### From source (local clone)

```bash
git clone https://github.com/ThainaJardim/observability-mcp.git
cd observability-mcp

pip install .

# For automatic Grafana SSO login via browser cookies (macOS/Linux):
pip install ".[browser-cookie]"
```

## Quick start

### Grafana / Loki

```bash
export GRAFANA_URL=https://grafana.example.com
export LOKI_DATASOURCE_ID=1          # numeric datasource ID in Grafana
export OIDC_ISSUER=https://keycloak.example.com/auth/realms/myrealm

grafana-mcp
```

### Thanos / Prometheus

```bash
export THANOS_URL=https://thanos.example.com
export OIDC_ISSUER=https://keycloak.example.com/auth/realms/myrealm

thanos-mcp
```

### Combined (both in one server)

```bash
# Set all env vars from above, then:
observability-mcp
```

## Authentication

### Grafana MCP

Auth mode is auto-detected from environment variables (or forced with
`GRAFANA_AUTH_MODE`):

| Mode | How it works | Variables needed |
|------|-------------|------------------|
| `browser-cookie` *(default)* | Reads Keycloak SSO cookies from Chrome, follows the Grafana OAuth flow automatically, caches `grafana_session` locally | `OIDC_ISSUER`, `GRAFANA_URL` |
| `token` | Grafana service-account token | `GRAFANA_BEARER_TOKEN` |
| `cookie` | Static `grafana_session` cookie | `GRAFANA_SESSION_COOKIE` |
| `kubeconfig` | OIDC id-token from kubectl kubeconfig | `OIDC_ISSUER` |

> **browser-cookie mode** requires `browser-cookie3` (`pip install ".[browser-cookie]"`).
> On first use it reads Chrome's cookie store — you may be prompted to allow
> macOS Keychain access.  You must be logged into Grafana in Chrome at least once.

### Thanos MCP

Auth mode is auto-detected (or forced with `THANOS_AUTH_MODE`):

| Mode | How it works | Variables needed |
|------|-------------|------------------|
| `kubeconfig` *(default)* | OIDC id-token from kubectl kubeconfig, auto-refreshed | `OIDC_ISSUER`, `kubectl` on PATH |
| `token` | Static Bearer token | `THANOS_ACCESS_TOKEN` |
| `cookie` | oauth2-proxy session cookie | `THANOS_SESSION_COOKIE` |

## Cursor MCP configuration

Create or edit `.cursor/mcp.json` in your project:

```json
{
  "mcpServers": {
    "grafana": {
      "command": "python",
      "args": ["-m", "grafana_mcp.server"],
      "env": {
        "GRAFANA_URL": "https://grafana.example.com",
        "LOKI_DATASOURCE_ID": "1",
        "OIDC_ISSUER": "https://keycloak.example.com/auth/realms/myrealm",
        "PATH": "/usr/local/bin:/usr/bin:/bin"
      }
    },
    "thanos": {
      "command": "python",
      "args": ["-m", "thanos_mcp.server"],
      "env": {
        "THANOS_URL": "https://thanos.example.com",
        "OIDC_ISSUER": "https://keycloak.example.com/auth/realms/myrealm",
        "PATH": "/usr/local/bin:/usr/bin:/bin"
      }
    }
  }
}
```

> **Tip:** Use an absolute Python interpreter path (e.g.
> `/usr/local/bin/python3`) if Cursor cannot find `python` in its PATH.

### Combined server (one entry)

```json
{
  "mcpServers": {
    "observability": {
      "command": "python",
      "args": ["-m", "observability_mcp.server"],
      "env": {
        "GRAFANA_URL": "https://grafana.example.com",
        "LOKI_DATASOURCE_ID": "1",
        "THANOS_URL": "https://thanos.example.com",
        "OIDC_ISSUER": "https://keycloak.example.com/auth/realms/myrealm",
        "PATH": "/usr/local/bin:/usr/bin:/bin"
      }
    }
  }
}
```

## Available MCP tools

### Grafana/Loki tools (`grafana_mcp`)

| Tool | Description |
|------|-------------|
| `query_loki_logs` | Run a LogQL range query and return matching log streams |
| `query_loki_instant` | Run a LogQL instant query |
| `list_loki_labels` | List all available Loki label names |
| `list_loki_label_values` | List values for a specific Loki label |

### Thanos/Prometheus tools (`thanos_mcp`)

| Tool | Description |
|------|-------------|
| `query_metrics` | Run an instant PromQL query |
| `query_metrics_range` | Run a PromQL range query |
| `list_labels` | List all metric label names |
| `list_series` | List time-series matching a selector |

## Development

```bash
# Install in editable mode with dev extras
pip install -e ".[dev,browser-cookie]"

# Run tests
pytest

# Run a specific server locally
python -m grafana_mcp.server
python -m thanos_mcp.server
python -m observability_mcp.server
```

## Environment variable reference

| Variable | Default | Description |
|----------|---------|-------------|
| `GRAFANA_URL` | *(required)* | Grafana base URL |
| `LOKI_DATASOURCE_ID` | *(required)* | Numeric Loki datasource ID in Grafana |
| `GRAFANA_AUTH_MODE` | auto | Force Grafana auth mode |
| `GRAFANA_BEARER_TOKEN` | — | Grafana service-account token |
| `GRAFANA_SESSION_COOKIE` | — | grafana_session cookie value |
| `GRAFANA_SESSION_CACHE` | `~/.cache/grafana-mcp/session.json` | Path to session cache file |
| `THANOS_URL` | *(required)* | Thanos/Prometheus base URL |
| `THANOS_AUTH_MODE` | auto | Force Thanos auth mode |
| `THANOS_ACCESS_TOKEN` | — | Static Bearer token |
| `THANOS_SESSION_COOKIE` | — | oauth2-proxy cookie value |
| `OIDC_ISSUER` | — | OIDC issuer URL (Keycloak realm URL) |
| `REQUEST_TIMEOUT_SECONDS` | `30` | HTTP timeout for all requests |
| `LOG_LEVEL` | `INFO` | Logging level |

## License

MIT

TDQS

A4.2/5.0

Scored across 8 tools

Disambiguation5/5

Each tool targets a distinct operation and data source (Loki vs. Thanos), with clear naming and descriptions that prevent confusion. Even similar tasks like label listing are differentiated by the datasource prefix.

Naming Consistency5/5

All tools follow a consistent verb_noun pattern in snake_case, e.g., 'query_loki_instant', 'list_labels'. The naming clearly indicates the action and the target, making it predictable and easy to understand.

Tool Count5/5

With 8 tools covering essential operations for two datasources (metrics and logs), the count is well-scoped. There are no redundant tools, and each tool serves a clear purpose without overwhelming the agent.

Completeness5/5

The tool set covers the core query and metadata exploration for both Loki and Thanos, including instant/range queries, label discovery, and series listing. No obvious gaps exist for standard observability workflows.

Maintenance

ActivityInactive
ResponsivenessNo issues