MCP Prometheus

Accede a métricas y consultas de Prometheus a través de interfaces MCP estandarizadas.

Documentación

MCP Prometheus

Un servidor MCP (Model Context Protocol) para Prometheus y Mimir, escrito en Go. Desplegado en el clúster en Giant Swarm para dar a los asistentes de IA acceso autenticado y multi-tenant a la infraestructura de métricas.

Qué hace

MCP Prometheus expone 18 herramientas MCP de solo lectura que envuelven la API HTTP de Prometheus: consultas PromQL instantáneas y por rango, descubrimiento de métricas/etiquetas/series, información de targets y runtime, estadísticas de TSDB, reglas de alerta y exemplars.

Cuando se despliega con OAuth habilitado, actúa como un Servidor de Autorización OAuth 2.1 completo (respaldado por Dex/OIDC o Google), por lo que los clientes MCP se autentican con el servidor antes de cualquier llamada a herramienta. El servidor entonces resuelve los IDs de tenant de Mimir del usuario autenticado y los aplica en cada consulta.


Contenido


Arquitectura

MCP Client (Claude, muster, …)
        │  OAuth 2.1 + MCP over HTTP
        ▼
┌──────────────────────────────────┐
│         mcp-prometheus           │
│                                  │
│  ┌────────────┐  ┌─────────────┐ │
│  │ OAuth 2.1  │  │  MCP Tools  │ │
│  │ server     │  │  (PromQL,   │ │
│  │ (mcp-oauth)│  │   labels, …)│ │
│  └─────┬──────┘  └──────┬──────┘ │
│        │                │        │
│  ┌─────▼──────┐  ┌──────▼──────┐ │
│  │ Dex OIDC   │  │  Tenancy    │ │
│  │ provider   │  │  resolver   │ │
│  └────────────┘  └──────┬──────┘ │
└─────────────────────────┼────────┘
                          │
          ┌───────────────┴──────────────┐
          │                              │
   ┌──────▼───────┐              ┌───────▼──────┐
   │ GrafanaOrg   │              │  Prometheus  │
   │ CRDs (k8s)   │              │  / Mimir     │
   └──────────────┘              └──────────────┘

El servidor escucha en dos puertos:

  • :8080 — endpoints MCP + OAuth (servidos a los clientes)
  • :9091 — observabilidad: /metrics, /healthz, /readyz (solo interno)

Instalación

Binarios precompilados

Descarga la última versión desde la página de releases.

Desde el código fuente

git clone https://github.com/giantswarm/mcp-prometheus.git
cd mcp-prometheus
go build -o mcp-prometheus ./...

Kubernetes (Helm)

Consulta Despliegue en Kubernetes (Helm).


Referencia de configuración

Toda la configuración se realiza mediante variables de entorno.

Conexión a Prometheus

VariablePredeterminadoDescripción
PROMETHEUS_URL—URL base de Prometheus/Mimir
PROMETHEUS_USERNAME—Usuario de autenticación básica
PROMETHEUS_PASSWORD—Contraseña de autenticación básica
PROMETHEUS_TOKEN—Token Bearer
PROMETHEUS_ORGID—ID de org/tenant predeterminado de Mimir
PROMETHEUS_TLS_SKIP_VERIFYfalseOmitir verificación TLS (solo desarrollo)
PROMETHEUS_TLS_CA_CERT—Ruta al certificado CA en formato PEM
ALERTMANAGER_URL—URL base de Alertmanager para get_alertmanager_alerts (Mimir: http://mimir-gateway.mimir/alertmanager); usa la autenticación, TLS y configuración de org ID anteriores

OAuth 2.1

VariablePredeterminadoDescripción
MCP_OAUTH_ISSUERobligatorioURL base pública de este servidor (p. ej. https://mcp.example.com)
MCP_OAUTH_ENCRYPTION_KEY—Clave AES-256-GCM de 32 bytes en base64 para cifrado de tokens (openssl rand -base64 32)
MCP_OAUTH_PROVIDERdexProveedor de identidad: dex o google (consulta las tablas de proveedores a continuación)
OAUTH_REDIRECT_URLobligatorioURL de callback registrada en el proveedor (p. ej. https://mcp.example.com/oauth/callback). El DEX_REDIRECT_URL heredado aún se respeta cuando esta no está definida
MCP_OAUTH_ALLOW_PUBLIC_REGISTRATIONfalsePermitir registro dinámico de clientes sin autenticación (solo desarrollo/Inspector MCP)
MCP_OAUTH_ALLOW_PRIVATE_URLSfalsePermitir descubrimiento OIDC contra Dex en IPs privadas/internas (consulta abajo); solo dex
OAUTH_TRUSTED_AUDIENCES—IDs de cliente separados por comas confiados para reenvío de tokens SSO
OAUTH_STORAGEmemoryAlmacenamiento de tokens: memory o valkey
VALKEY_URL—Dirección de Valkey/Redis (obligatoria cuando OAUTH_STORAGE=valkey)
VALKEY_PASSWORD—Contraseña de autenticación de Valkey
VALKEY_TLS_ENABLEDfalseHabilitar TLS para Valkey
VALKEY_KEY_PREFIXmcp:Prefijo del espacio de nombres de claves

Proveedor OIDC Dex (MCP_OAUTH_PROVIDER=dex)

VariablePredeterminadoDescripción
DEX_ISSUER_URLobligatorioURL del emisor de Dex (p. ej. https://dex.mc.example.io)
DEX_CLIENT_IDobligatorioID de cliente OAuth registrado en Dex
DEX_CLIENT_SECRETobligatorioSecreto de cliente OAuth
DEX_REDIRECT_URL—Alias heredado de OAUTH_REDIRECT_URL; se usa cuando este último no está definido
DEX_CA_FILE—Archivo CA PEM que verifica TLS para endpoints Dex y JWKS (instalaciones con CA privada). Se añade sobre el almacén de confianza del sistema

Proveedor Google (MCP_OAUTH_PROVIDER=google)

VariablePredeterminadoDescripción
GOOGLE_CLIENT_IDobligatorioID de cliente OAuth del cliente OAuth de Google Cloud (….apps.googleusercontent.com)
GOOGLE_CLIENT_SECRETobligatorioSecreto de cliente OAuth de ese cliente

Los endpoints de descubrimiento, token y JWKS de Google son públicos, por lo que DEX_CA_FILE y MCP_OAUTH_ALLOW_PRIVATE_URLS no aplican (se ignoran con una advertencia). Los tokens de ID de Google no llevan claim groups: combina este proveedor con el modo de tenancy none o con una lista estática de tenants para todos los usuarios.

Tenancy

VariablePredeterminadoDescripción
TENANCY_STATIC_GROUP_MAP—Mapa JSON de grupo Dex → lista de IDs de tenant de Mimir (modo estático)

El modo de tenancy es un flag: --tenancy-mode grafana-organization|static|none (consulta Multi-tenancy).

Observabilidad

VariablePredeterminadoDescripción
OTEL_EXPORTER_OTLP_ENDPOINT—Endpoint OTLP HTTP para tracing (sin operación si no está definido)
OTEL_SERVICE_NAMEmcp-prometheusNombre del servicio en los traces

Modos de transporte

Inicia el servidor con serve --transport <mode>:

ModoFlagCaso de uso
stdio--transport stdioClientes de escritorio locales (Claude Desktop, MCP Inspector)
sse--transport sseClientes SSE heredados
streamable-http--transport streamable-httpProducción en clúster (predeterminado)

OAuth requiere sse o streamable-http.

# Local stdio (no OAuth)
./mcp-prometheus serve

# In-cluster HTTP with OAuth
./mcp-prometheus serve --transport streamable-http --http-addr :8080 --enable-oauth

Autenticación OAuth 2.1

MCP Prometheus implementa OAuth 2.1 (RFC 9700) usando mcp-oauth con el proveedor de identidad de la plataforma como upstream: Dex (predeterminado) o Google, seleccionado con MCP_OAUTH_PROVIDER. El flujo, los endpoints y el manejo de tokens son idénticos para ambos; solo difieren el inicio de sesión upstream y las variables de entorno específicas del proveedor.

Endpoints

RutaMétodoPropósito
/.well-known/oauth-authorization-serverGETMetadatos del servidor OAuth (RFC 8414)
/.well-known/protected-resourcesGETMetadatos del recurso protegido
/oauth/authorizeGETEndpoint de autorización (redirige al proveedor de identidad)
/oauth/callbackGETCallback del proveedor de identidad (OAUTH_REDIRECT_URL)
/oauth/tokenPOSTIntercambio de tokens
/oauth/registerPOSTRegistro dinámico de clientes (RFC 7591)
/oauth/revokePOSTRevocación de tokens

Flujo OAuth completo

MCP Client                mcp-prometheus              Dex OIDC
    │                           │                        │
    │  1. GET /.well-known/…    │                        │
    │──────────────────────────>│                        │
    │  server metadata          │                        │
    │<──────────────────────────│                        │
    │                           │                        │
    │  2. POST /oauth/register  │                        │
    │──────────────────────────>│                        │
    │  client_id + secret       │                        │
    │<──────────────────────────│                        │
    │                           │                        │
    │  3. GET /oauth/authorize  │                        │
    │──────────────────────────>│                        │
    │                           │  4. redirect to Dex    │
    │                           │───────────────────────>│
    │<──────────────────────────────────────────────────│
    │  browser: Dex login UI    │                        │
    │  (user authenticates)     │                        │
    │                           │                        │
    │                           │  5. callback + code    │
    │                           │<───────────────────────│
    │                           │                        │
    │  6. POST /oauth/token     │                        │
    │──────────────────────────>│                        │
    │  access_token + refresh   │                        │
    │<──────────────────────────│                        │
    │                           │                        │
    │  7. MCP tool call         │                        │
    │  Authorization: Bearer …  │                        │
    │──────────────────────────>│                        │
    │                           │  8. validate token     │
    │                           │  resolve tenants       │
    │                           │  forward to Mimir      │

El token de acceso es un JWT de corta duración firmado por mcp-prometheus y validado en cada solicitud. La rotación del refresh token está habilitada: cada renovación emite un nuevo refresh token.

Almacenamiento de tokens

  • memory (predeterminado): en proceso, se pierde al reiniciar. Adecuado para despliegues de una sola réplica y desarrollo.
  • valkey: backend Redis/Valkey de nivel producción. Obligatorio para despliegues multi-réplica.

Permitir URLs privadas

Cuando DEX_ISSUER_URL usa un nombre DNS interno que resuelve a una IP privada (rango RFC-1918), la protección SSRF integrada en el cliente de descubrimiento OIDC rechazaría la conexión.

Establece MCP_OAUTH_ALLOW_PRIVATE_URLS=true para permitir conexiones a IPs privadas hacia ese Dex para el descubrimiento OIDC y para la obtención de JWKS que valida los tokens de ID reenviados (OAUTH_TRUSTED_AUDIENCES, p. ej. desde muster). La URL de JWKS proviene del emisor Dex configurado, nunca del token. La verificación TLS sigue aplicándose.

MCP_OAUTH_ALLOW_PRIVATE_URLS=true
DEX_ISSUER_URL=https://dex.mc.my-cluster.example.io   # resolves to 10.x.x.x

En Helm: app.oauth.allowPrivateURLs: true

CA privada (DEX_CA_FILE)

Cuando Dex se sirve con un certificado de una CA privada/interna (p. ej. clústeres de gestión privados), la verificación TLS falla con x509: certificate signed by unknown authority. Apunta DEX_CA_FILE a un archivo CA PEM para añadir esa CA sobre el almacén de confianza del sistema. El pool verifica la conexión con el proveedor Dex (descubrimiento OIDC, flujo de código, userinfo) y el endpoint JWKS del token de ID reenviado.

DEX_CA_FILE=/etc/ssl/certs/dex-ca/ca.crt

En Helm, referencia un Secret que contenga el certificado CA:

app:
  oauth:
    dexCASecret:
      name: mcp-prometheus-dex-ca
      key: ca.crt

Reenvío de tokens SSO (trustedAudiences)

Cuando los usuarios se conectan a través de un agregador MCP upstream (p. ej. muster) que ya los ha autenticado, el agregador puede reenviar el token de ID del usuario desde el IdP de la plataforma directamente en lugar de iniciar un nuevo flujo OAuth.

Configura OAUTH_TRUSTED_AUDIENCES con una lista separada por comas de los IDs de cliente OAuth del agregador:

OAUTH_TRUSTED_AUDIENCES=muster-client,my-aggregator

mcp-prometheus:

  1. Detectará que la audiencia del token entrante coincide con un ID de cliente confiado
  2. Verificará la firma del token contra el endpoint JWKS del proveedor (Dex o Google)
  3. Aceptará el token y procederá con la resolución de tenant

Los tokens deben originarse del emisor del proveedor configurado. Con el proveedor Google, lista el ID de cliente OAuth de Google de la plataforma (aquel con el que muster inicia sesión para los usuarios) aquí.


Multi-tenancy

Cuando OAuth está habilitado, cada llamada a herramienta se limita a los IDs de tenant de Mimir permitidos del usuario autenticado. El usuario puede pasar un parámetro explícito org_id; el servidor lo valida contra sus tenants permitidos. Si no se proporciona org_id, todos los tenants permitidos se inyectan como un selector multi-tenant de Mimir separado por barras verticales.

Hay tres modos de resolución disponibles, seleccionados con --tenancy-mode (o app.tenancy.mode en Helm): grafana-organization (predeterminado), static y none.

Modo GrafanaOrganization (predeterminado)

--tenancy-mode grafana-organization

Lee los recursos personalizados GrafanaOrganization de la API de Kubernetes. Cada CR declara qué grupos de Dex tienen acceso (spec.rbac) y qué IDs de tenant de Mimir le corresponden (spec.tenants).

apiVersion: observability.giantswarm.io/v1alpha1
kind: GrafanaOrganization
metadata:
  name: team-platform
spec:
  rbac:
    - groupName: github-org:team-platform   # Dex group from LDAP/GitHub
  tenants:
    - prod-eu-west
    - prod-us-east

Cuando un usuario se autentica:

  1. El servidor lee el claim groups de su token de Dex
  2. Busca todos los CR GrafanaOrganization donde cualquier grupo en spec.rbac coincida
  3. Recopila todos los IDs de tenant de spec.tenants en los CR coincidentes
  4. Los resultados se cachean por conjunto de grupos durante 60 segundos

El chart de Helm crea un ClusterRole + ClusterRoleBinding que otorga get, list, watch sobre grafanaorganizations.observability.giantswarm.io cuando este modo está activo.

Modo estático

--tenancy-mode static

No requiere acceso a la API de Kubernetes. Los tenants se configuran estáticamente.

Todos los usuarios: mismos tenants para todos

# All authenticated users get these tenant IDs
--static-tenants=prod-eu,prod-us

Helm:

app:
  tenancy:
    mode: static
    static:
      tenants: "prod-eu,prod-us"

Mapeo por grupos: asignación de tenants por grupo

Cuando TENANCY_STATIC_GROUP_MAP está definido (o app.tenancy.static.groups en Helm), los IDs de tenant se resuelven por grupo:

TENANCY_STATIC_GROUP_MAP='{"team-ops":["prod-eu","prod-us"],"team-dev":["staging"]}'

Helm:

app:
  tenancy:
    mode: static
    static:
      groups:
        team-ops:
          - prod-eu
          - prod-us
        team-dev:
          - staging

Los tenants permitidos del usuario son la unión de todos los tenants de sus grupos de Dex.

Modo None (Prometheus de un solo tenant)

--tenancy-mode none

Para un Prometheus simple de un solo tenant (sin Mimir, sin X-Scope-OrgID). OAuth aún autentica a cada llamador: las solicitudes no autenticadas se rechazan, los tokens reenviados se validan y la identidad está disponible para auditoría — pero no se deriva ningún tenant de la identidad ni se inyecta ninguna cabecera de tenant. Un parámetro de herramienta explícito org_id o PROMETHEUS_ORGID se pasa tal cual. El chart no crea ningún ClusterRole en este modo.

Este es el modo a usar con el proveedor Google (los tokens de Google no tienen claim groups) y siempre que mcp-prometheus esté detrás de muster frente a un único Prometheus.

Helm:

app:
  tenancy:
    mode: none

Herramientas disponibles

Todas las herramientas aceptan parámetros opcionales prometheus_url y org_id para anulaciones por llamada.

Ejecución de consultas

HerramientaDescripción
mcp_prometheus_execute_queryConsulta instantánea PromQL
mcp_prometheus_execute_range_queryConsulta por rango PromQL con start, end, step

Las herramientas de consulta aceptan: timeout, limit, stats, lookback_delta, unlimited.

Métricas y descubrimiento

HerramientaDescripción
mcp_prometheus_get_metric_metadataMetadatos de una métrica específica
mcp_prometheus_list_label_namesTodos los nombres de etiquetas
mcp_prometheus_list_label_valuesValores para una etiqueta específica
mcp_prometheus_find_seriesBuscar series por coincidencias de etiquetas

Objetivos e información del sistema

HerramientaDescripción
mcp_prometheus_get_targetsLista de objetivos de scrape y estado de salud
mcp_prometheus_get_build_infoInformación de compilación/versión
mcp_prometheus_get_runtime_infoInformación de tiempo de ejecución
mcp_prometheus_get_flagsBanderas de tiempo de ejecución
mcp_prometheus_get_configConfiguración de Prometheus
mcp_prometheus_get_tsdb_statsEstadísticas de cardinalidad de TSDB
mcp_prometheus_check_readyVerificación de disponibilidad (/-/ready), funciona con Mimir

Alertas y reglas

HerramientaDescripción
mcp_prometheus_get_alertsAlertas activas
mcp_prometheus_get_alertmanagersDescubrimiento de AlertManager
mcp_prometheus_get_rulesReglas de grabación y alertas
mcp_prometheus_get_alertmanager_alertsAlertas que notifican, desde Alertmanager: activas, no silenciadas, no inhibidas

get_rules acepta los filtros de GET /api/v1/rules, aplicados del lado del servidor por Prometheus o el ruler de Mimir: type (alert o record), rule_name, rule_group, file (el espacio de nombres de reglas de Mimir) y exclude_alerts. Los coincidentes de etiquetas (match[]) no están expuestos porque el ruler de Mimir los ignora. En Mimir pase org_id — la API del ruler rechaza solicitudes sin un tenant.

get_alertmanager_alerts lee GET /api/v2/alerts del Alertmanager en alertmanager_url o ALERTMANAGER_URL y devuelve las alertas que notifican, primero las más antiguas, cada una con su huella digital, nombre de alerta, severidad, hora de inicio, etiquetas, anotaciones y receptores. filter toma coincidentes de etiquetas (team="bumblebee", severity=~"page|notify") y receiver una expresión regular de receptor; ambos son aplicados por el Alertmanager. El tenant se resuelve como para cada herramienta de Prometheus, por lo que en Mimir el Alertmanager multi-tenant se lee con el X-Scope-OrgID del llamante.

Avanzado

HerramientaDescripción
mcp_prometheus_query_exemplarsConsultas de exemplars para correlación de trazas
mcp_prometheus_get_targets_metadataMetadatos de métricas por objetivo

Los resultados de consultas grandes se truncan automáticamente con orientación para que la IA refine su consulta.


Despliegue en Kubernetes (Helm)

Mínimo (sin OAuth)

app:
  env:
    - name: PROMETHEUS_URL
      value: "http://mimir-gateway.monitoring:8080/prometheus"
    - name: PROMETHEUS_ORGID
      value: "my-tenant"

Producción con OAuth + tenencia de GrafanaOrganization

app:
  server:
    transport: streamable-http

  oauth:
    enabled: true
    dexClientSecret: "..."        # stored in K8s Secret
    encryptionKey: "..."          # openssl rand -hex 32
    storage:
      type: valkey
      valkey:
        url: "valkey:6379"
    trustedAudiences:
      - muster-client

  tenancy:
    mode: grafana-organization

  env:
    - name: MCP_OAUTH_ISSUER
      value: "https://mcp-prometheus.mc.example.io"
    - name: DEX_ISSUER_URL
      value: "https://dex.mc.example.io"
    - name: DEX_CLIENT_ID
      value: "mcp-prometheus"
    - name: DEX_REDIRECT_URL
      value: "https://mcp-prometheus.mc.example.io/oauth/callback"
    - name: PROMETHEUS_URL
      value: "http://mimir-gateway.monitoring:8080/prometheus"

Proveedor de Google + Prometheus de un solo tenant detrás de muster

El IdP de la plataforma es Google, muster reenvía el token de ID de Google del usuario (auth.forwardToken: true), y no hay tenants de Mimir que resolver.

app:
  oauth:
    enabled: true
    provider: google
    redirectURL: "https://mcp-prometheus.example.io/oauth/callback"
    google:
      clientID: "1234567890-abc.apps.googleusercontent.com"   # this server's OAuth client
    googleClientSecret: "..."   # or existingSecret with key GOOGLE_CLIENT_SECRET
    encryptionKey: "..."        # openssl rand -base64 32
    trustedAudiences:
      - "1234567890-platform.apps.googleusercontent.com"       # the platform client muster logs in with

  tenancy:
    mode: none

  env:
    - name: MCP_OAUTH_ISSUER
      value: "https://mcp-prometheus.example.io"
    - name: PROMETHEUS_URL
      value: "http://prometheus-operated.monitoring:9090"

Producción con OAuth + mapeo de grupos estático

app:
  oauth:
    enabled: true
    dexClientSecret: "..."
    encryptionKey: "..."

  tenancy:
    mode: static
    static:
      groups:
        team-ops:
          - prod-eu
          - prod-us
        team-dev:
          - staging

Dex privado (DNS interno)

Cuando DEX_ISSUER_URL se resuelve a una IP privada:

app:
  oauth:
    enabled: true
    allowPrivateURLs: true    # private-IP Dex: OIDC discovery and forwarded-token JWKS
    dexClientSecret: "..."
    encryptionKey: "..."

Almacenamiento de tokens Valkey (multi-réplica)

app:
  oauth:
    storage:
      type: valkey
      valkey:
        url: "valkey.default:6379"
        password: ""
        tlsEnabled: false
        keyPrefix: "mcp-prometheus:"

Desarrollo

Estructura del proyecto

mcp-prometheus/
├── cmd/                      # CLI (serve, version)
├── internal/
│   ├── oauth/                # OAuth 2.1 setup (Config, NewHandler)
│   ├── server/               # ServerContext, PrometheusConfig
│   ├── tenancy/              # TenancyResolver, GrafanaOrg + static modes
│   ├── tools/prometheus/     # 18 MCP tool registrations
│   └── observability/        # /metrics, /healthz, /readyz, OTel
├── helm/mcp-prometheus/      # Helm chart
├── go.mod
└── README.md

Compilación y pruebas

go build -o mcp-prometheus ./...
go test ./...

Convenciones de código

  • Cada paquete tiene un doc.go
  • Cobertura de pruebas unitarias del 80%+ en código nuevo
  • Ejecute goimports -w . && go fmt ./... antes de confirmar
  • Archivos mantenidos por debajo de 500 líneas; GoDoc en todos los miembros exportados