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
- Instalación
- Referencia de configuración
- Modos de transporte
- Autenticación OAuth 2.1
- Multi-tenant
- Herramientas disponibles
- Despliegue en Kubernetes (Helm)
- Desarrollo
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
| Variable | Predeterminado | Descripción |
|---|---|---|
PROMETHEUS_URL | — | URL base de Prometheus/Mimir |
PROMETHEUS_USERNAME | — | Nombre de 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 de Mimir predeterminado |
PROMETHEUS_TLS_SKIP_VERIFY | false | Omitir verificación TLS (solo desarrollo) |
PROMETHEUS_TLS_CA_CERT | — | Ruta al certificado CA PEM |
OAuth 2.1
| Variable | Predeterminado | Descripción |
|---|---|---|
MCP_OAUTH_ISSUER | requerido | URL base pública de este servidor (p. ej. https://mcp.example.com) |
MCP_OAUTH_ENCRYPTION_KEY | — | Clave AES-256-GCM base64 de 32 bytes para cifrado de tokens (openssl rand -base64 32) |
MCP_OAUTH_ALLOW_PUBLIC_REGISTRATION | false | Permitir registro dinámico de clientes sin autenticación (solo dev/MCP Inspector) |
MCP_OAUTH_ALLOW_PRIVATE_URLS | false | Permitir descubrimiento OIDC contra Dex en IPs privadas/internas (ver abajo) |
OAUTH_TRUSTED_AUDIENCES | — | IDs de cliente separados por comas confiables para el reenvío de tokens SSO |
OAUTH_STORAGE | memory | Almacenamiento de tokens: memory o valkey |
VALKEY_URL | — | Dirección de Valkey/Redis (requerida cuando OAUTH_STORAGE=valkey) |
VALKEY_PASSWORD | — | Contraseña de autenticación de Valkey |
VALKEY_TLS_ENABLED | false | Habilitar TLS para Valkey |
VALKEY_KEY_PREFIX | mcp: | Prefijo de espacio de nombres de claves |
Proveedor OIDC Dex
| Variable | Predeterminado | Descripción |
|---|---|---|
DEX_ISSUER_URL | requerido | URL del emisor Dex (p. ej. https://dex.mc.example.io) |
DEX_CLIENT_ID | requerido | ID de cliente OAuth registrado en Dex |
DEX_CLIENT_SECRET | requerido | Secreto de cliente OAuth |
DEX_REDIRECT_URL | requerido | URL de callback (p. ej. https://mcp.example.com/oauth/callback) |
DEX_CA_FILE | — | Archivo 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
| Variable | Predeterminado | Descripción |
|---|---|---|
TENANCY_STATIC_GROUP_MAP | — | Mapa JSON de grupo Dex → lista de IDs de tenant de Mimir (modo estático) |
Observabilidad
| Variable | Predeterminado | Descripción |
|---|---|---|
OTEL_EXPORTER_OTLP_ENDPOINT | — | Endpoint HTTP OTLP para trazado (sin efecto si no se establece) |
OTEL_SERVICE_NAME | mcp-prometheus | Nombre del servicio en los traces |
Modos de transporte
Inicia el servidor con serve --transport <mode>:
| Modo | Flag | Caso de uso |
|---|---|---|
stdio | --transport stdio | Clientes de escritorio locales (Claude Desktop, MCP Inspector) |
sse | --transport sse | Clientes SSE heredados |
streamable-http | --transport streamable-http | Producció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
| Ruta | Método | Propósito |
|---|---|---|
/.well-known/oauth-authorization-server | GET | Metadatos del servidor OAuth (RFC 8414) |
/.well-known/protected-resources | GET | Metadatos de recurso protegido |
/oauth/authorize | GET | Endpoint de autorización (redirige a Dex) |
/oauth/callback | GET | Callback de Dex |
/oauth/token | POST | Intercambio de tokens |
/oauth/register | POST | Registro dinámico de clientes (RFC 7591) |
/oauth/revoke | POST | Revocació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:
- Detectará que la audiencia del token entrante coincide con un ID de cliente confiable
- Verificará la firma del token contra el endpoint JWKS de Dex
- 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:
- El servidor lee el claim
groupsde su token Dex - Busca todos los CR
GrafanaOrganizationdonde cualquier grupo enspec.rbaccoincida - Recopila todos los IDs de tenant de
spec.tenantsen los CR coincidentes - 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
| Herramienta | Descripción |
|---|---|
mcp_prometheus_execute_query | Consulta instantánea PromQL |
mcp_prometheus_execute_range_query | Consulta de rango PromQL con start, end, step |
Las herramientas de consulta aceptan: timeout, limit, stats, lookback_delta, unlimited.
Métricas y descubrimiento
| Herramienta | Descripción |
|---|---|
mcp_prometheus_get_metric_metadata | Metadatos para una métrica específica |
mcp_prometheus_list_label_names | Todos los nombres de etiquetas |
mcp_prometheus_list_label_values | Valores para una etiqueta específica |
mcp_prometheus_find_series | Encontrar series por selectores de etiquetas |
Targets e información del sistema
| Herramienta | Descripción |
|---|---|
mcp_prometheus_get_targets | Lista de targets de scrape y estado |
mcp_prometheus_get_build_info | Información de compilación/versión |
mcp_prometheus_get_runtime_info | Información de runtime |
mcp_prometheus_get_flags | Flags de runtime |
mcp_prometheus_get_config | Configuración de Prometheus |
mcp_prometheus_get_tsdb_stats | Estadísticas de cardinalidad de TSDB |
mcp_prometheus_check_ready | Comprobación de disponibilidad (/-/ready), funciona con Mimir |
Alertas y reglas
| Herramienta | Descripción |
|---|---|
mcp_prometheus_get_alerts | Alertas activas |
mcp_prometheus_get_alertmanagers | Descubrimiento de AlertManager |
mcp_prometheus_get_rules | Reglas de grabación y alerta |
Avanzado
| Herramienta | Descripción |
|---|---|
mcp_prometheus_query_exemplars | Consultas de exemplars para correlación de traces |
mcp_prometheus_get_targets_metadata | Metadatos 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