MCP Prometheus

Acesse métricas e consultas do Prometheus por meio de interfaces MCP padronizadas.

Documentação

MCP Prometheus

Um servidor MCP (Model Context Protocol) para Prometheus e Mimir, escrito em Go. Implantado no cluster na Giant Swarm para dar a assistentes de IA acesso autenticado e multi-tenant à infraestrutura de métricas.

O que ele faz

O MCP Prometheus expõe 18 ferramentas MCP somente leitura que encapsulam a API HTTP do Prometheus: consultas PromQL instantâneas e por intervalo, descoberta de métricas/rótulos/séries, informações de alvos e runtime, estatísticas do TSDB, regras de alerta e exemplares.

Quando implantado com OAuth habilitado, ele atua como um Servidor de Autorização OAuth 2.1 completo (com suporte a Dex/OIDC ou Google), para que clientes MCP se autentiquem no servidor antes de qualquer chamada de ferramenta. O servidor então resolve os IDs de tenant Mimir do usuário autenticado e os aplica em todas as consultas.


Conteúdo


Arquitetura

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     │
   └──────────────┘              └──────────────┘

O servidor escuta em duas portas:

  • :8080 — endpoints MCP + OAuth (servidos aos clientes)
  • :9091 — observabilidade: /metrics, /healthz, /readyz (somente interno)

Instalação

Binários pré-compilados

Baixe a versão mais recente na página de releases.

A partir do código-fonte

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

Kubernetes (Helm)

Consulte Implantação Kubernetes (Helm).


Referência de configuração

Toda a configuração é feita por meio de variáveis de ambiente.

Conexão Prometheus

VariávelPadrãoDescrição
PROMETHEUS_URL—URL base do Prometheus/Mimir
PROMETHEUS_USERNAME—Nome de usuário para autenticação básica
PROMETHEUS_PASSWORD—Senha para autenticação básica
PROMETHEUS_TOKEN—Token Bearer
PROMETHEUS_ORGID—ID de org/tenant Mimir padrão
PROMETHEUS_TLS_SKIP_VERIFYfalseIgnorar verificação TLS (somente desenvolvimento)
PROMETHEUS_TLS_CA_CERT—Caminho para certificado CA PEM

OAuth 2.1

VariávelPadrãoDescrição
MCP_OAUTH_ISSUERobrigatórioURL base pública deste servidor (ex.: https://mcp.example.com)
MCP_OAUTH_ENCRYPTION_KEY—Chave AES-256-GCM base64 de 32 bytes para criptografia de tokens (openssl rand -base64 32)
MCP_OAUTH_PROVIDERdexProvedor de identidade: dex ou google (consulte as tabelas de provedores abaixo)
OAUTH_REDIRECT_URLobrigatórioURL de callback registrada no provedor (ex.: https://mcp.example.com/oauth/callback). O DEX_REDIRECT_URL legado ainda é respeitado quando este não está definido
MCP_OAUTH_ALLOW_PUBLIC_REGISTRATIONfalsePermitir registro dinâmico de clientes não autenticados (somente desenvolvimento/MCP Inspector)
MCP_OAUTH_ALLOW_PRIVATE_URLSfalsePermitir descoberta OIDC contra Dex em IPs privados/internos (consulte abaixo); somente dex
OAUTH_TRUSTED_AUDIENCES—IDs de clientes separados por vírgula confiáveis para encaminhamento de token SSO
OAUTH_STORAGEmemoryArmazenamento de tokens: memory ou valkey
VALKEY_URL—Endereço Valkey/Redis (obrigatório quando OAUTH_STORAGE=valkey)
VALKEY_PASSWORD—Senha de autenticação Valkey
VALKEY_TLS_ENABLEDfalseHabilitar TLS para Valkey
VALKEY_KEY_PREFIXmcp:Prefixo do namespace de chaves

Provedor Dex OIDC (MCP_OAUTH_PROVIDER=dex)

VariávelPadrãoDescrição
DEX_ISSUER_URLobrigatórioURL do emissor Dex (ex.: https://dex.mc.example.io)
DEX_CLIENT_IDobrigatórioID do cliente OAuth registrado no Dex
DEX_CLIENT_SECRETobrigatórioSegredo do cliente OAuth
DEX_REDIRECT_URL—Alias legado de OAUTH_REDIRECT_URL; usado quando este não está definido
DEX_CA_FILE—Arquivo CA PEM para verificar TLS para endpoints Dex e JWKS (instalações com CA privada). Adicionado sobre o armazenamento de confiança do sistema

Provedor Google (MCP_OAUTH_PROVIDER=google)

VariávelPadrãoDescrição
GOOGLE_CLIENT_IDobrigatórioID do cliente OAuth do cliente OAuth do Google Cloud (….apps.googleusercontent.com)
GOOGLE_CLIENT_SECRETobrigatórioSegredo do cliente OAuth desse cliente

Os endpoints de descoberta, token e JWKS do Google são públicos, portanto DEX_CA_FILE e MCP_OAUTH_ALLOW_PRIVATE_URLS não se aplicam (são ignorados com um aviso). Os tokens de ID do Google não carregam a declaração groups: combine este provedor com modo de tenancy none ou uma lista estática de tenants para todos os usuários.

Tenancy

VariávelPadrãoDescrição
TENANCY_STATIC_GROUP_MAP—Mapa JSON de grupo Dex → lista de IDs de tenant Mimir (modo estático)

O modo de tenancy é uma flag: --tenancy-mode grafana-organization|static|none (consulte Multi-tenancy).

Observabilidade

VariávelPadrãoDescrição
OTEL_EXPORTER_OTLP_ENDPOINT—Endpoint HTTP OTLP para rastreamento (sem operação se não definido)
OTEL_SERVICE_NAMEmcp-prometheusNome do serviço nos rastreamentos

Modos de transporte

Inicie o servidor com serve --transport <mode>:

ModoFlagCaso de uso
stdio--transport stdioClientes desktop locais (Claude Desktop, MCP Inspector)
sse--transport sseClientes SSE legados
streamable-http--transport streamable-httpProdução no cluster (padrão)

OAuth requer sse ou 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

Autenticação OAuth 2.1

O MCP Prometheus implementa OAuth 2.1 (RFC 9700) usando mcp-oauth com o provedor de identidade da plataforma upstream: Dex (padrão) ou Google, selecionado com MCP_OAUTH_PROVIDER. O fluxo, os endpoints e o manuseio de tokens são idênticos para ambos; apenas o login upstream e as variáveis de ambiente específicas do provedor diferem.

Endpoints

CaminhoMétodoFinalidade
/.well-known/oauth-authorization-serverGETMetadados do servidor OAuth (RFC 8414)
/.well-known/protected-resourcesGETMetadados do recurso protegido
/oauth/authorizeGETEndpoint de autorização (redireciona para o provedor de identidade)
/oauth/callbackGETCallback do provedor de identidade (OAUTH_REDIRECT_URL)
/oauth/tokenPOSTTroca de tokens
/oauth/registerPOSTRegistro dinâmico de clientes (RFC 7591)
/oauth/revokePOSTRevogação de tokens

Fluxo 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      │

O token de acesso é um JWT de curta duração assinado pelo mcp-prometheus e validado em todas as requisições. A rotação de refresh tokens está habilitada — cada atualização emite um novo refresh token.

Armazenamento de tokens

  • memory (padrão): em processo, perdido na reinicialização. Adequado para implantações de réplica única e desenvolvimento.
  • valkey: backend Redis/Valkey de nível de produção. Obrigatório para implantações com múltiplas réplicas.

Permitir URLs privadas

Quando DEX_ISSUER_URL usa um nome DNS interno que resolve para um IP privado (faixa RFC-1918), a proteção SSRF embutida no cliente de descoberta OIDC rejeitaria a conexão.

Defina MCP_OAUTH_ALLOW_PRIVATE_URLS=true para injetar um cliente HTTP que permita conexões com IPs privados para descoberta OIDC. A verificação TLS ainda é aplicada.

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

No Helm: app.oauth.allowPrivateURLs: true

CA privada (DEX_CA_FILE)

Quando o Dex é servido com um certificado de uma CA privada/interna (ex.: clusters de gerenciamento privados), a verificação TLS falha com x509: certificate signed by unknown authority. Aponte DEX_CA_FILE para um arquivo CA PEM para adicionar essa CA sobre o armazenamento de confiança do sistema. O pool verifica a conexão do provedor Dex (descoberta OIDC, fluxo de código, userinfo), o endpoint JWKS do token de ID encaminhado e os endpoints JWKS de emissores confiáveis.

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

No Helm, referencie um Secret contendo o certificado CA:

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

Encaminhamento de token SSO (trustedAudiences)

Quando usuários se conectam por meio de um agregador MCP upstream (ex.: muster) que já os autenticou, o agregador pode encaminhar o token de ID do usuário do IdP da plataforma diretamente, em vez de iniciar um novo fluxo OAuth.

Configure OAUTH_TRUSTED_AUDIENCES com uma lista separada por vírgulas dos IDs de cliente OAuth do agregador:

OAUTH_TRUSTED_AUDIENCES=muster-client,my-aggregator

O mcp-prometheus irá:

  1. Detectar que o público do token recebido corresponde a um ID de cliente confiável
  2. Verificar a assinatura do token contra o endpoint JWKS do provedor (Dex ou Google)
  3. Aceitar o token e prosseguir com a resolução de tenant

Os tokens devem ainda ser originados do emissor do provedor configurado. Com o provedor Google, liste o ID do cliente OAuth do Google da plataforma (aquele com o qual o muster autentica usuários) aqui.


Multi-tenancy

Quando o OAuth está habilitado, toda chamada de ferramenta é limitada aos IDs de tenant Mimir permitidos do usuário autenticado. O usuário pode passar um parâmetro explícito org_id; o servidor o valida contra seus tenants permitidos. Se nenhum org_id for fornecido, todos os tenants permitidos são injetados como um seletor multi-tenant Mimir separado por pipe.

Três modos de resolução estão disponíveis, selecionados com --tenancy-mode (ou app.tenancy.mode no Helm): grafana-organization (padrão), static e none.

Modo GrafanaOrganization (padrão)

--tenancy-mode grafana-organization

Lê recursos personalizados GrafanaOrganization da API Kubernetes. Cada CR declara quais grupos Dex têm acesso (spec.rbac) e quais IDs de tenant Mimir mapeiam para ele (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

Quando um usuário se autentica:

  1. O servidor lê a declaração groups do token Dex do usuário
  2. Ele busca todos os CRs GrafanaOrganization onde qualquer grupo em spec.rbac corresponde
  3. Ele coleta todos os IDs de tenant de spec.tenants nos CRs correspondentes
  4. Os resultados são armazenados em cache por conjunto de grupos por 60 segundos

O chart Helm cria um ClusterRole + ClusterRoleBinding concedendo get, list, watch em grafanaorganizations.observability.giantswarm.io quando este modo está ativo.

Modo estático

--tenancy-mode static

Nenhum acesso à API Kubernetes é necessário. Os tenants são configurados estaticamente.

Todos os usuários: mesmos 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"

Mapeamento de grupos: atribuição de tenant por grupo

Quando TENANCY_STATIC_GROUP_MAP está definido (ou app.tenancy.static.groups no Helm), os IDs de tenant são resolvidos 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

Os tenants permitidos do usuário são a união de todos os tenants de seus grupos Dex.

Modo None (Prometheus de tenant único)

--tenancy-mode none

Para um Prometheus simples de tenant único (sem Mimir, sem X-Scope-OrgID). O OAuth ainda autentica todo chamador — requisições não autenticadas são rejeitadas, tokens encaminhados são validados e a identidade está disponível para auditoria — mas nenhum tenant é derivado da identidade e nenhum cabeçalho de tenant é injetado. Um parâmetro explícito de ferramenta org_id ou PROMETHEUS_ORGID é repassado literalmente. O chart não cria ClusterRole neste modo.

Este é o modo a ser usado com o provedor Google (tokens do Google não têm a declaração groups) e sempre que o mcp-prometheus estiver atrás do muster na frente de um único Prometheus.

Helm:

app:
  tenancy:
    mode: none

Ferramentas disponíveis

Todas as ferramentas aceitam parâmetros opcionais prometheus_url e org_id para substituições por chamada.

Execução de consultas

FerramentaDescrição
mcp_prometheus_execute_queryConsulta instantânea PromQL
mcp_prometheus_execute_range_queryConsulta por intervalo PromQL com start, end, step

As ferramentas de consulta aceitam: timeout, limit, stats, lookback_delta, unlimited.

Métricas e descoberta

FerramentaDescrição
mcp_prometheus_get_metric_metadataMetadados para uma métrica específica
mcp_prometheus_list_label_namesTodos os nomes de rótulos
mcp_prometheus_list_label_valuesValores para um rótulo específico
mcp_prometheus_find_seriesEncontrar séries por seletores de rótulos

Alvos e informações do sistema

FerramentaDescrição
mcp_prometheus_get_targetsLista de alvos e saúde
mcp_prometheus_get_build_infoInformações de build/versão
mcp_prometheus_get_runtime_infoInformações de runtime
mcp_prometheus_get_flagsFlags de runtime
mcp_prometheus_get_configConfiguração do Prometheus
mcp_prometheus_get_tsdb_statsEstatísticas de cardinalidade do TSDB
mcp_prometheus_check_readyVerificação de prontidão (/-/ready), funciona com Mimir

Alertas e regras

FerramentaDescrição
mcp_prometheus_get_alertsAlertas ativos
mcp_prometheus_get_alertmanagersDescoberta do AlertManager
mcp_prometheus_get_rulesRegras de gravação e alertas

get_rules aceita os filtros de GET /api/v1/rules, aplicados no lado do servidor pelo Prometheus ou pelo ruler do Mimir: type (alert ou record), rule_name, rule_group, file (o namespace de regras do Mimir) e exclude_alerts. Os seletores de rótulos (match[]) não são expostos porque o ruler do Mimir os ignora. No Mimir, passe org_id — a API do ruler rejeita requisições sem um tenant.

Avançado

FerramentaDescrição
mcp_prometheus_query_exemplarsConsultas de exemplares para correlação de traces
mcp_prometheus_get_targets_metadataMetadados de métricas por alvo

Resultados grandes de consultas são truncados automaticamente com orientação para a IA refinar sua consulta.


Implantação no Kubernetes (Helm)

Mínimo (sem OAuth)

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

Produção com OAuth + locação 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"

Provedor Google + Prometheus de tenant único atrás do muster

O IdP da plataforma é o Google, o muster encaminha o token de ID do Google do usuário (auth.forwardToken: true), e não há tenants do Mimir para 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"

Produção com OAuth + mapeamento de grupo 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)

Quando DEX_ISSUER_URL resolve para um IP privado:

app:
  oauth:
    enabled: true
    allowPrivateURLs: true    # enables private-IP OIDC discovery
    dexClientSecret: "..."
    encryptionKey: "..."

Armazenamento de tokens Valkey (multi-réplica)

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

Desenvolvimento

Estrutura do projeto

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

Build e testes

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

Convenções de código

  • Cada pacote tem um doc.go
  • Cobertura de testes unitários de 80%+ em código novo
  • Execute goimports -w . && go fmt ./... antes de commitar
  • Arquivos mantidos abaixo de 500 linhas; GoDoc em todos os membros exportados