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 de 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), de modo que los clientes MCP se autentican con el servidor antes de cualquier llamada a herramienta. El servidor resuelve entonces 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_URLURL base de Prometheus/Mimir
PROMETHEUS_USERNAMENombre de usuario de autenticación básica
PROMETHEUS_PASSWORDContraseña de autenticación básica
PROMETHEUS_TOKENToken Bearer
PROMETHEUS_ORGIDID de org/tenant de Mimir predeterminado
PROMETHEUS_TLS_SKIP_VERIFYfalseOmitir verificación TLS (solo desarrollo)
PROMETHEUS_TLS_CA_CERTRuta al certificado CA PEM

OAuth 2.1

VariablePredeterminadoDescripción
MCP_OAUTH_ISSUERrequeridoURL base pública de este servidor (p. ej. https://mcp.example.com)
MCP_OAUTH_ENCRYPTION_KEYClave AES-256-GCM base64 de 32 bytes para cifrado de tokens (openssl rand -base64 32)
MCP_OAUTH_ALLOW_PUBLIC_REGISTRATIONfalsePermitir registro dinámico de clientes sin autenticación (solo dev/MCP Inspector)
MCP_OAUTH_ALLOW_PRIVATE_URLSfalsePermitir descubrimiento OIDC contra Dex en IPs privadas/internas (ver abajo)
OAUTH_TRUSTED_AUDIENCESIDs de cliente separados por comas confiables para el reenvío de tokens SSO
OAUTH_STORAGEmemoryAlmacenamiento de tokens: memory o valkey
VALKEY_URLDirección de Valkey/Redis (requerida cuando OAUTH_STORAGE=valkey)
VALKEY_PASSWORDContraseña de autenticación de Valkey
VALKEY_TLS_ENABLEDfalseHabilitar TLS para Valkey
VALKEY_KEY_PREFIXmcp:Prefijo de espacio de nombres de claves

Proveedor OIDC Dex

VariablePredeterminadoDescripción
DEX_ISSUER_URLrequeridoURL del emisor Dex (p. ej. https://dex.mc.example.io)
DEX_CLIENT_IDrequeridoID de cliente OAuth registrado en Dex
DEX_CLIENT_SECRETrequeridoSecreto de cliente OAuth
DEX_REDIRECT_URLrequeridoURL de callback (p. ej. https://mcp.example.com/oauth/callback)
DEX_CA_FILEArchivo CA PEM que verifica TLS para los endpoints de Dex y JWKS (instalaciones con CA privada). Se añade sobre el almacén de confianza del sistema

Tenancy

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

Observabilidad

VariablePredeterminadoDescripción
OTEL_EXPORTER_OTLP_ENDPOINTEndpoint HTTP OTLP para trazado (sin efecto si no se establece)
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 y Dex como proveedor de identidad OIDC.

Endpoints

RutaMétodoPropósito
/.well-known/oauth-authorization-serverGETMetadatos del servidor OAuth (RFC 8414)
/.well-known/protected-resourcesGETMetadatos de recurso protegido
/oauth/authorizeGETEndpoint de autorización (redirige a Dex)
/oauth/callbackGETCallback de Dex
/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 de tokens de refresco está habilitada: cada refresco emite un nuevo token de refresco.

Almacenamiento de tokens

  • memory (predeterminado): en proceso, se pierde al reiniciar. Adecuado para despliegues de réplica única y desarrollo.
  • valkey: backend Redis/Valkey de nivel producción. Requerido 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 inyectar un cliente HTTP que permita conexiones a IPs privadas para el descubrimiento OIDC. 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), el endpoint JWKS del token ID reenviado y los endpoints JWKS de emisores confiables.

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 token SSO (trustedAudiences)

Cuando los usuarios se conectan a través de un agregador MCP ascendente (p. ej. muster) que ya los ha autenticado, el agregador puede reenviar directamente el token ID de Dex del usuario 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 confiable
  2. Verificará la firma del token contra el endpoint JWKS de Dex
  3. Aceptará el token y continuará con la resolución de tenants

Los tokens deben seguir originándose del emisor Dex configurado.


Multi-tenant

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 org_id explícito; 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 dos modos de resolución disponibles, seleccionados con --tenancy-mode (o app.tenancy.mode en Helm).

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 se asignan a él (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 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: los 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 de grupos: asignación de tenants por grupo

Cuando TENANCY_STATIC_GROUP_MAP está establecido (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 Dex.


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 de 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 para 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_seriesEncontrar series por selectores de etiquetas

Targets e información del sistema

HerramientaDescripción
mcp_prometheus_get_targetsLista de targets de scrape y estado
mcp_prometheus_get_build_infoInformación de compilación/versión
mcp_prometheus_get_runtime_infoInformación de runtime
mcp_prometheus_get_flagsFlags de runtime
mcp_prometheus_get_configConfiguración de Prometheus
mcp_prometheus_get_tsdb_statsEstadísticas de cardinalidad de TSDB
mcp_prometheus_check_readyComprobació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 alerta

Avanzado

HerramientaDescripción
mcp_prometheus_query_exemplarsConsultas de exemplars para correlación de traces
mcp_prometheus_get_targets_metadataMetadatos de métricas por target

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 + tenancy 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"

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 resuelve a una IP privada:

app:
  oauth:
    enabled: true
    allowPrivateURLs: true    # enables private-IP OIDC discovery
    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
  • Ejecuta goimports -w . && go fmt ./... antes de hacer commit
  • Archivos de menos de 500 líneas; GoDoc en todos los miembros exportados