Helm MCP

Servidor MCP para trabalhar com charts Helm

Documentação

Servidor MCP Helm

Um servidor MCP (Model Context Protocol) que fornece ferramentas para interagir com repositórios e charts Helm. Este servidor permite que assistentes de IA consultem repositórios Helm, obtenham informações de charts e acessem valores de charts sem exigir instalação local do Helm.

O propósito de usar MCP para Helm é evitar inventar o formato de values.yaml e o conteúdo dos charts ao trabalhar com LLMs. Em vez disso, o servidor fornece uma maneira padronizada de acessar essas informações, facilitando para assistentes de IA interagir com charts e repositórios Helm.

Este servidor MCP fornece e fornecerá ferramentas para trabalhar apenas com repositórios Helm. Se você precisar trabalhar com outros recursos Kubernetes, considere usar um servidor MCP separado que forneça ferramentas para recursos Kubernetes.

Recursos

O servidor MCP Helm fornece as seguintes ferramentas:

  • list_repository_charts - Lista todos os charts disponíveis em um repositório Helm (ou nome do chart para registries OCI)
  • list_chart_versions - Lista todas as versões/tags disponíveis para um chart
  • get_latest_version_of_chart - Recupera a versão estável mais recente (não-pré-lançamento) de um chart específico
  • get_chart_values - Recupera o arquivo de valores de um chart (versão mais recente ou versão específica)
  • get_chart_contents - Recupera o conteúdo de um chart (incluindo templates, valores e metadados), opcionalmente filtrado por padrões glob de caminho de arquivo (por exemplo, templates/**)
  • get_chart_dependencies - Recupera as dependências de um chart conforme definido em seu arquivo Chart.yaml
  • get_chart_images - Extrai imagens de contêiner usadas em um chart Helm renderizando templates e analisando manifestos Kubernetes

Tipos de Repositório

Todas as ferramentas suportam tanto repositórios Helm HTTP tradicionais quanto registries OCI:

Tipo de RepositórioURL de Exemplo
Repositório HTTPhttps://charts.example.com
Registry OCIoci://ghcr.io/org/charts/mychart
OCI (Docker Hub)oci://docker.io/library/mysql

Suporte a Registry OCI

Registries OCI (Open Container Initiative) armazenam charts Helm como artefatos OCI. Diferente de repositórios HTTP onde múltiplos charts compartilham um índice, registries OCI tipicamente contêm um chart por repositório com múltiplas tags de versão.

Exemplo de uso com OCI:

repository_url: oci://ghcr.io/nginxinc/charts/nginx-ingress
chart_name: (empty - chart name is in the URL)

Experimente sem instalação

Existe uma instância publicamente disponível do servidor MCP Helm que você pode usar para testar os recursos sem instalá-lo: https://mcp-helm.zekker.dev/mcp

Instalação

Executar com docker

Você pode executar o servidor MCP Helm usando Docker. Esta é a maneira mais fácil de começar sem precisar instalar Go ou compilar a partir do código-fonte.

docker run -d --name mcp-helm -p 8012:8012 ghcr.io/zekker6/mcp-helm:v1.3.0 -mode=sse

Observe que o sinalizador --mode=sse é usado para habilitar o modo Server-Sent Events, que é usado pelos clientes MCP para conectar. Alternativamente, você pode usar -mode=http para habilitar o modo HTTP Streamable.

Via binário pré-compilado

Baixe o binário da página de releases.

Exemplo para Linux x86_64 (observe que outras arquiteturas e plataformas também estão disponíveis):

latest=$(curl -s https://api.github.com/repos/zekker6/mcp-helm/releases/latest | grep 'tag_name' | cut -d\" -f4)
wget https://github.com/zekker6/mcp-helm/releases/download/$latest/mcp-helm_Linux_x86_64.tar.gz
tar axvf mcp-helm_Linux_x86_64.tar.gz

Via Mise

Mise (mise-en-place) é uma ferramenta de configuração de ambiente de desenvolvimento.

mise i ubi:zekker6/mcp-helm@latest

Instalar com Go

Nota: Go 1.26.0 é necessário.

go install github.com/zekker6/mcp-helm/cmd/mcp-helm@latest

Compilar a partir do código-fonte

Nota: Go 1.26.0 é necessário.

  1. Clone o repositório:

    git clone https://github.com/zekker6/mcp-helm.git
    cd mcp-helm
    
  2. Compile o binário:

    go build -o mcp-helm ./cmd/mcp-helm
    
  3. Execute o servidor:

    ./mcp-helm
    

Configuração

Configure seu cliente MCP para conectar a este servidor. O servidor implementa o protocolo MCP padrão para descoberta e execução de ferramentas.

Nos modos http e sse, os corpos POST são limitados a 8 MiB. Solicitações maiores recebem HTTP 413, incluindo uploads em partes sem Content-Length. O servidor HTTP permite 5 segundos para cabeçalhos de solicitação, 30 segundos para cabeçalhos e corpo juntos, e 60 segundos para conexões ociosas. Respostas SSE não têm prazo de gravação e podem permanecer abertas além desses orçamentos de leitura de solicitação. Esses limites não limitam o trabalho realizado por uma chamada de ferramenta aceita.

Cache de índice de repositório

O índice de um repositório Helm HTTP é baixado no primeiro uso e reutilizado por -repo-index-max-age (padrão 1h). Uma vez que essa idade é excedida, a próxima solicitação baixa o índice novamente, então versões de charts recém-publicadas aparecem sem reinicialização. Defina -repo-index-max-age=0 para baixar o índice em cada solicitação. Registries OCI são sempre consultados ao vivo.

Por padrão, cada cliente retém no máximo 16 índices de repositório com um orçamento de bytes de origem derivado de sua alocação de memória na inicialização, removendo os índices menos recentemente usados quando qualquer limite é atingido. O servidor MCP compartilha um cliente Helm e seu cache entre solicitações. Objetos Go analisados adicionam sobrecarga de memória; isso não é um limite de heap do processo. A remoção não altera snapshots já mantidos por solicitações ativas. Arquivos de índice usam um diretório temporário privado que é removido após a análise, incluindo em falha de download ou análise. Arquivos de chart HTTP são carregados diretamente da memória. Arquivos existentes em diretórios de cache Helm compartilhados não são lidos ou excluídos. Snapshots em cache não retêm contextos de solicitação ou clientes de download.

Limites de cache e download

Os padrões são constantes nomeadas em lib/helm_client/limits.go e lib/helm_client/memory.go. Substitua-os com variáveis de ambiente lidas ao criar o cliente Helm. Os valores devem ser inteiros decimais positivos, com limites de bytes expressos em bytes, não em MiB ou outras unidades com sufixo. Uma variável não definida usa seu padrão; valores vazios, zero, negativos, malformados ou estourados falham na inicialização. Clientes existentes não recarregam mudanças no ambiente. O sinalizador -repo-index-max-age ainda controla o TTL.

Variável de ambientePadrãoControla
MCP_HELM_REPO_CACHE_MAX_ENTRIES16Contagem de índices de repositório retidos
MCP_HELM_REPO_CACHE_MAX_BYTESAutomático, descrito abaixoTotal de bytes de origem de índice retidos
MCP_HELM_INDEX_MAX_BYTES33554432 (32 MiB)Bytes por download de índice HTTP
MCP_HELM_CHART_MAX_BYTES104857600 (100 MiB)Bytes por arquivo de chart HTTP compactado
MCP_HELM_OCI_MAX_BYTES134217728 (128 MiB)Total de bytes do corpo de resposta por pull OCI

Quando MCP_HELM_REPO_CACHE_MAX_BYTES não está definido, o cliente usa 1/16 da menor alocação de memória detectada, limitada a 256 MiB. Ele considera limites cgroup v1/v2 do Linux, incluindo limites pai visíveis, o limite de memória atual do runtime Go inicializado por GOMEMLIMIT, e RAM total do host. Ele não usa memória livre flutuante ou solicitações de memória Kubernetes. Este cálculo nunca altera o limite de memória do Go.

Alocação de memóriaOrçamento automático de bytes de origem de cache
512 MiB32 MiB
1 GiB64 MiB
2 GiB128 MiB
4 GiB ou mais256 MiB

Se nenhum limite puder ser detectado, o cliente usa 64 MiB como fallback. Um erro de detecção, como um controlador de contêiner ilegível, limita o resultado a 64 MiB enquanto preserva qualquer orçamento menor detectado. Logs de inicialização relatam o modo de dimensionamento, orçamento selecionado, alocação detectada e origem quando disponível, e qualquer erro de detecção. Nenhum redimensionamento em segundo plano é executado; mudanças de alocação entram em vigor quando um novo cliente inicia. Uma substituição explícita de bytes ignora a detecção e o limite automático. Em alocações pequenas, um índice válido maior que o orçamento de cache pode ser baixado, mas não será retido. Esses orçamentos de bytes de origem não são limites de heap medidos e não previnem OOM de trabalho concorrente.

O orçamento OCI inclui manifestos, configuração, camadas de chart, respostas de autenticação, redirecionamentos e novas tentativas. Pulls concorrentes têm orçamentos independentes. Respostas sem Content-Length são verificadas durante a leitura; downloads superdimensionados falham em vez de serem truncados e analisados. Esses limites não limitam solicitações concorrentes ou memória de renderização de charts. O limite de conteúdo de chart descompactado do Helm ainda se aplica. Downloads OCI honram tanto o cancelamento do chamador quanto o cancelamento da solicitação do registry, incluindo durante a leitura de corpos de resposta.

Por exemplo, permita um conjunto de trabalho maior e índices individuais maiores:

env MCP_HELM_REPO_CACHE_MAX_ENTRIES=32 \
    MCP_HELM_REPO_CACHE_MAX_BYTES=134217728 \
    MCP_HELM_INDEX_MAX_BYTES=67108864 \
    ./mcp-helm -mode=http

Validando um servidor compartilhado

Execute task test:repos para buscar índices atuais de Prometheus Community, Grafana, Bitnami, Jetstack, Argo e ingress-nginx. Ele verifica o conjunto de trabalho contra os limites configurados, reproduz esses índices exatos localmente com oito chamadores concorrentes, verifica a reutilização de cache quente e baixa um chart representativo de cada repositório público. A fase de carga repetida não acessa servidores públicos. O teste registra tamanhos de origem, latência, falhas e uso de heap Go quiescente, que inclui os fixtures de teste capturados e não é RSS do processo. Falhas de endpoint público ou formato de chart falham no teste em vez de serem ignoradas. task test mantém esta verificação de rede desabilitada; task test:all compila o binário e executa os testes de unidade, ponta a ponta e de repositório público juntos. CI executa task test:all após linting, então a verificação de repositório público também controla mudanças. Para índices que referenciam charts OCI, também testa a referência OCI direta separadamente. O carregador de repositório HTTP atualmente não segue URLs de arquivo oci://, incluindo o chart nginx da Bitnami; use a URL de repositório OCI direta para esses charts. Esta falha de compatibilidade permanece visível no teste público.

Os testes regulares também exercitam oito clientes MCP HTTP independentes contra repositórios locais, incluindo remoção forçada de cache e downloads repetidos de charts. Uma execução bem-sucedida é uma verificação de regressão de compatibilidade e concorrência, não uma garantia de capacidade de produção. Os limites de cache limitam a retenção, não o número de usuários ativos. Buscas de índice frio ainda compartilham um bloqueio global, e arquivos de chart são baixados em cada solicitação. Dimensione o limite de índice para o maior repositório e o limite de bytes de cache para o conjunto de trabalho completo usado com frequência, com espaço para crescimento.

Autenticação

O servidor suporta autenticação para registries OCI e repositórios Helm HTTP.

Ao incorporar o cliente Go, downloads de repositório HTTP clonam http.DefaultTransport se for um *http.Transport. Se estiver envolvido ou substituído por outro http.RoundTripper, downloads usam um transporte privado com suporte a proxy de ambiente. O wrapper não é usado; as opções TLS do repositório do cliente ainda se aplicam.

Sinalizadores de Linha de Comando

SinalizadorDescrição
-usernameNome de usuário para autenticação básica (repositórios HTTP e registries OCI não cobertos por -registry-credentials)
-password-fileCaminho para arquivo contendo senha
-registry-credentialsCaminho para arquivo de credenciais estilo Docker (ex.: ~/.docker/config.json); autoritativo para os registries OCI que lista
-registry-plain-httpUsar HTTP simples para registries OCI (inseguro, apenas para desenvolvimento)
-tls-certCaminho para arquivo de certificado TLS do cliente para repositórios HTTP
-tls-keyCaminho para arquivo de chave TLS do cliente para repositórios HTTP
-tls-caCaminho para arquivo de certificado CA para verificar certificados de servidor
-tls-insecure-skip-verifyPular verificação de certificado TLS (inseguro)
-pass-credentials-allEnviar credenciais de repositório HTTP para todas as URLs de charts e origens de redirecionamento (inseguro)
As credenciais de repositório HTTP vão para o próprio esquema, host e porta do repositório por padrão. Arquivos de chart em outras origens ainda podem ser baixados, mas não recebem credenciais do repositório, inclusive após redirecionamentos ou um rebaixamento de HTTPS para HTTP. -pass-credentials-all opta por enviar essas credenciais para cada URL de chart e origem de redirecionamento. Use-o apenas quando você confiar nas URLs de chart do repositório e em cada destino de redirecionamento.

Autenticação Básica

Para repositórios que exigem autenticação por nome de usuário/senha:

# Create a password file (recommended for security)
echo "your-password" > /path/to/password.txt
chmod 600 /path/to/password.txt

# Run with basic auth
./mcp-helm -username myuser -password-file /path/to/password.txt

Autenticação de Registro OCI

Para registros OCI privados, a autenticação pode ser configurada via:

  1. Credenciais Docker - O servidor usa automaticamente as credenciais de ~/.docker/config.json
  2. Arquivo de credenciais explícito - Use a flag -registry-credentials
# Using Docker login (credentials stored in ~/.docker/config.json)
docker login ghcr.io
echo $GITHUB_TOKEN | docker login ghcr.io -u USERNAME --password-stdin

# Using explicit credentials file
./mcp-helm -registry-credentials /path/to/docker/config.json

# Using basic auth for OCI registry
./mcp-helm -username myuser -password-file /path/to/password.txt
Combinando autenticação básica com um arquivo de credenciais de registro

Uma única instância pode atender repositórios HTTP privados e registros OCI privados ao mesmo tempo. Quando tanto -username/-password-file quanto -registry-credentials estão definidos, as solicitações OCI são roteadas por host de registro:

  • Se o arquivo de credenciais resolver uma credencial para o host de registro do chart, essa credencial por host é usada (auths, credHelpers e credsStore são todos consultados, usando a mesma resolução de credenciais Docker que o CLI Helm, então a chave canônica https://index.docker.io/v1/ do Docker Hub é correspondida corretamente).
  • Caso contrário, a autenticação básica estática -username/-password-file é usada.

Isso permite que -registry-credentials permaneça autoritativo para os registros OCI que cobre, enquanto a autenticação básica ainda se aplica a repositórios HTTP (e a qualquer registro OCI que o arquivo de credenciais não resolva).

# HTTP repos use basic auth; OCI hosts in config.json use their per-host creds
./mcp-helm \
  -username myuser -password-file /path/to/password.txt \
  -registry-credentials /path/to/docker/config.json

Credenciais atrás de um armazenamento de credenciais externo (credsStore) ou auxiliar por registro (credHelpers) são resolvidas invocando esse binário auxiliar em tempo de execução. Se o auxiliar não estiver disponível no ambiente de execução, os registros afetados voltam para autenticação básica; um aviso é registrado na inicialização para que isso seja visível. O roteamento considera apenas o arquivo passado para -registry-credentials (sem fallback implícito de ~/.docker/config.json), então liste cada registro OCI privado que você precisa nesse arquivo.

Configuração TLS/mTLS

Para repositórios com requisitos TLS personalizados:

# Custom CA certificate (for self-signed or internal CAs)
./mcp-helm -tls-ca /path/to/ca.crt

# Client certificate authentication (mTLS)
./mcp-helm -tls-cert /path/to/client.crt -tls-key /path/to/client.key

# Combined: mTLS with custom CA
./mcp-helm -tls-cert client.crt -tls-key client.key -tls-ca ca.crt

# Skip TLS verification (development only, not recommended for production)
./mcp-helm -tls-insecure-skip-verify

Configuração Docker

Exemplo com Docker, passando autenticação:

# With basic auth
docker run -d --name mcp-helm -p 8012:8012 \
  -v /path/to/password.txt:/secrets/password.txt:ro \
  ghcr.io/zekker6/mcp-helm:v1.3.0 \
  -mode=sse -username myuser -password-file /secrets/password.txt

# With Docker credentials
docker run -d --name mcp-helm -p 8012:8012 \
  -v ~/.docker/config.json:/root/.docker/config.json:ro \
  ghcr.io/zekker6/mcp-helm:v1.3.0 \
  -mode=sse

Observabilidade

O servidor pode exportar traces, métricas e logs do OpenTelemetry via OTLP. Está desabilitado por padrão: com OTEL_ENABLED não definido, nada é exportado, nenhum exporter é construído, nenhum provider é registrado globalmente e nenhuma instrumentação é instalada, então o binário se comporta exatamente como hoje.

OTEL_ENABLED é o único interruptor. OTEL_SDK_DISABLED não é consultado, e nem OTEL_EXPORTER_OTLP_PROTOCOL: o protocolo de transmissão vem do esquema do endpoint, descrito abaixo.

Variáveis de Ambiente

VariávelPadrãoDescrição
OTEL_ENABLEDfalseInterruptor mestre. A telemetria é configurada apenas quando isso contém um valor verdadeiro (true, 1, t)
OTEL_EXPORTER_OTLP_ENDPOINT-Endpoint base para todos os três sinais. Obrigatório quando habilitado, a menos que cada endpoint por sinal esteja definido
OTEL_EXPORTER_OTLP_TRACES_ENDPOINTendpoint baseSubstituição apenas para traces, usada literalmente (inclua o caminho completo para HTTP)
OTEL_EXPORTER_OTLP_METRICS_ENDPOINTendpoint baseSubstituição apenas para métricas, usada literalmente
OTEL_EXPORTER_OTLP_LOGS_ENDPOINTendpoint baseSubstituição apenas para logs, usada literalmente
OTEL_SERVICE_NAMEmcp-helmNome do serviço relatado ao collector
OTEL_RESOURCE_ATTRIBUTES-Atributos de recurso extras, ex.: deployment.environment.name=production
OTEL_EXPORTER_OTLP_HEADERS-Cabeçalhos enviados com cada exportação, ex.: para autenticação. Lidos pelos exporters do SDK
OTEL_EXPORTER_OTLP_TIMEOUT10000Tempo limite de exportação em milissegundos. Lido pelos exporters do SDK
OTEL_EXPORTER_OTLP_COMPRESSION-Defina como gzip para comprimir exportações. Lido pelos exporters do SDK
OTEL_METRIC_EXPORT_INTERVAL60000Intervalo de exportação de métricas em milissegundos
OTEL_EXPORTER_OTLP_METRICS_DEFAULT_HISTOGRAM_AGGREGATIONbase2_exponential_bucket_histogramAgregação de histograma para ambos os transportes OTLP. Defina como explicit_bucket_histogram para buckets clássicos
OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCEcumulativeContadores e histogramas acumulam desde seu início ou redefinição. O SDK também aceita delta e lowmemory
OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT4096Valor mais longo de atributo de span; os mais longos são truncados. O padrão do SDK é ilimitado, mas vários valores vêm de clientes. OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT tem precedência, e -1 remove o limite
OTEL_EXPORTER_OTLP_CERTIFICATEraízes do sistemaPacote de CA PEM usado para verificar um collector https:// ou grpcs://. Lido pelos exporters do SDK
OTEL_EXPORTER_OTLP_CLIENT_CERTIFICATE-Certificado de cliente PEM para mTLS ao collector. Lido pelos exporters do SDK
OTEL_EXPORTER_OTLP_CLIENT_KEY-Chave de cliente PEM para mTLS ao collector. Lido pelos exporters do SDK

Quando a telemetria está habilitada e um endpoint está ausente ou malformado, o servidor sai com código não zero e um erro nomeando a variável problemática; um erro de digitação nunca degrada silenciosamente para "sem telemetria". Com OTEL_ENABLED desligado, as variáveis de endpoint não são analisadas, então um valor obsoleto no ambiente não pode quebrar a inicialização.

Atributos de Recurso

O servidor define service.name (de OTEL_SERVICE_NAME, senão mcp-helm) e service.version ele mesmo, e lê qualquer outra coisa de OTEL_RESOURCE_ATTRIBUTES. As convenções semânticas pedem mais do que isso, e o restante tem que vir da implantação:

AtributoDe onde deve vir
deployment.environment.nameOTEL_RESOURCE_ATTRIBUTES. Observe o sufixo .name - deployment.environment puro é descontinuado
service.instance.idOTEL_RESOURCE_ATTRIBUTES da API downward. Obrigatório quando mais de uma réplica roda, ou as séries de cada instância colidem
service.namespaceOTEL_RESOURCE_ATTRIBUTES, quando outros serviços compartilham o backend
k8s.pod.uid e outros k8s.*O processador k8sattributes do Collector, que é a forma suportada de adicioná-los

No Kubernetes, os dois primeiros vêm da API downward:

env:
  - name: POD_NAME
    valueFrom:
      fieldRef:
        fieldPath: metadata.name
  - name: OTEL_RESOURCE_ATTRIBUTES
    value: deployment.environment.name=production,service.instance.id=$(POD_NAME)

Esquemas de Endpoint

O protocolo de transmissão e o TLS vêm do esquema de URL do endpoint:

EndpointProtocoloTLSExportações vão para
grpc://collector:4317OTLP/gRPCnãocollector:4317
grpcs://otel.example.com:4317OTLP/gRPCsimotel.example.com:4317
http://collector:4318OTLP/HTTPnãohttp://collector:4318/v1/traces, /v1/metrics, /v1/logs
https://otel.example.comOTLP/HTTPsimhttps://otel.example.com/v1/traces, /v1/metrics, /v1/logs

Qualquer outro esquema é um erro de inicialização nomeando os quatro esquemas aceitos.

  • O endpoint base é uma URL base: para HTTP, o caminho do sinal (/v1/traces, /v1/metrics, /v1/logs) é anexado, após remover uma barra final. Um endpoint de collector injetado com barra final é tratado.
  • Um endpoint por sinal é usado literalmente, como a especificação OTLP exige, então para HTTP ele tem que carregar o caminho completo incluindo /v1/traces e afins.
  • Endpoints gRPC mantêm apenas host:port; gRPC não tem caminho de sinal, então qualquer caminho é descartado.
  • O protocolo é resolvido por sinal, então configurações mistas funcionam: traces via gRPC enquanto métricas e logs vão via HTTP é uma configuração suportada. Para logs, grpcs:// exige TLS mesmo sem uma CA personalizada; use OTEL_EXPORTER_OTLP_CERTIFICATE ou OTEL_EXPORTER_OTLP_LOGS_CERTIFICATE para uma CA privada.

Exemplos de Configuração

Um endpoint para todos os três sinais:

OTEL_ENABLED=true \
OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector:4318 \
./mcp-helm -mode=http

Traces, métricas e logs são enviados para http://otel-collector:4318/v1/traces, /v1/metrics e /v1/logs. Trocar esse endpoint para grpc://otel-collector:4317 move todos os três sinais para OTLP/gRPC sem qualquer outra mudança.

Endpoints por sinal, misturando protocolos e TLS:

OTEL_ENABLED=true \
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=grpc://otel-collector:4317 \
OTEL_EXPORTER_OTLP_METRICS_ENDPOINT=https://metrics.example.com/v1/metrics \
OTEL_EXPORTER_OTLP_LOGS_ENDPOINT=https://logs.example.com/v1/logs \
OTEL_SERVICE_NAME=mcp-helm \
OTEL_RESOURCE_ATTRIBUTES=deployment.environment.name=production \
./mcp-helm -mode=http

Com Docker:

docker run -d --name mcp-helm -p 8012:8012 \
  -e OTEL_ENABLED=true \
  -e OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector:4318 \
  ghcr.io/zekker6/mcp-helm:latest -mode=http

As variáveis OTEL_* são ignoradas por imagens construídas antes do suporte ao OpenTelemetry, então fixe uma tag que tenha isso ou use latest.

O Que É Emitido

Traces

Uma chamada de ferramenta via HTTP produz um trace da solicitação de entrada até o trabalho Helm que ela aciona:

POST /mcp                       (HTTP server span)
  tools/call get_chart_images   (MCP server span)
    tool.get_chart_images       (MCP tool span)
      helm.get_chart_images     (Helm operation span)
        helm.load_chart
          helm.oci.pull
        helm.parse.images

Nomes de telemetria personalizados usam o namespace mcp_helm.* específico do aplicativo, sem um domínio pessoal. Os atributos específicos do Helm abaixo omitem seu prefixo mcp_helm.helm. para legibilidade; os nomes emitidos o incluem. Diretrizes de nomenclatura do OpenTelemetry recomendam evitar colisões com namespaces padrão, não um prefixo reverso de DNS obrigatório. Atributos de registro (url.full, server.address, server.port, error.type, gen_ai.*, mcp.*, jsonrpc.*, rpc.*) são mostrados por extenso. Consultas existentes usando o namespace personalizado anterior devem ser atualizadas; nomes OTel padrão não mudam.

SpanKindAttributes
<METHOD> <route>servidorotelhttp convenções semânticas de servidor HTTP, além da mensagem JSON-RPC que um POST carregou (abaixo). Somente nos modos sse e http
<mcp method> [<tool>]servidormcp.method.name, jsonrpc.request.id, gen_ai.tool.name, gen_ai.operation.name, mcp.session.id, mcp.protocol.version, network.transport, network.protocol.name, rpc.response.status_code, error.type
tool.<name>interno-
helm.list_chartsinternorepository.url, repository.type, chart.count
helm.list_chart_versionsinterno+ chart.name, version.count
helm.get_latest_versioninterno+ chart.name, chart.version (resolvido)
helm.get_latest_valuesinterno+ chart.name, chart.version (resolvido). Somente biblioteca; nenhuma ferramenta MCP o alcança
helm.get_chart_valuesinterno+ chart.name, chart.version
helm.get_chart_contentsinterno+ chart.name, chart.version, recursive
helm.get_chart_dependenciesinterno+ chart.name, chart.version, dependency.count
helm.get_chart_imagesinterno+ chart.name, chart.version, recursive, image.count
helm.load_chartinternorepository.type, chart.name, chart.version
helm.oci.pullclienteoci.ref, server.address, server.port
helm.oci.tagsclienteoci.ref, server.address, server.port
helm.repo.indexclienterepository.url, server.address, server.port
helm.chart.downloadclienteurl.full, server.address, server.port
helm.parse.imagesinternorecursive
helm.parse.contentsinternorecursive

Um span com falha é marcado com um status ERROR, registra a exceção e carrega error.type. Os atributos de URL são saneados: user:password@ userinfo é removido antes que uma URL de repositório, OCI ou chart se torne um atributo de span.

O span helm.chart.download relata url.full porque a URL do chart é o recurso exato buscado. helm.repo.index não: o getter do Helm resolve o caminho do índice por conta própria, então a URL que este servidor mantém não é a solicitada.

O span do servidor MCP segue as convenções semânticas do MCP: ele é nomeado {mcp.method.name} {target}, como tools/call get_chart_values, tools/list ou ping. Somente uma ferramenta registrada se torna o alvo, pois o cliente escolhe o nome; uma não registrada ainda alcança gen_ai.tool.name. Um método que o mcp-go não implementa é registrado como mcp.method.name=_OTHER em um span nomeado MCP, da mesma forma que a instrumentação HTTP trata um método desconhecido, então um cliente não pode cunhar um nome de span por solicitação. O servidor rastreia por meio de seu próprio adaptador para a interface de rastreamento do mcp-go em vez de github.com/mark3labs/mcp-go/otel, e omite as chaves mcp.method e mcp.tool.name que o mcp-go define: o registro não define nenhuma delas. Spans de método desconhecido atualmente omitem jsonrpc.request.id porque o mcp-go não expõe o ID ao rastreador ou aos ganchos de erro nesse caminho. A correção adiada requer suporte da API upstream.

mcp.protocol.version registra a versão efetiva da solicitação somente quando o mcp-go a reconhece. Valores de metadados não suportados e cabeçalhos de protocolo brutos não são copiados para spans ou métricas. network.transport é tcp nos modos sse e http, juntamente com network.protocol.name=http, e pipe no modo stdio.

Uma solicitação respondida com um erro JSON-RPC carrega o código em rpc.response.status_code. O atributo das convenções -32700, -32600, -32601, -32602 (que inclui uma ferramenta desconhecida) e -32002 ao chamador, então esses deixam error.type não definido e o status do span UNSET. Qualquer outro código define error.type para o código e o status para ERROR, descrito pela mensagem de erro JSON-RPC. Um manipulador de ferramenta que relatou a falha ao seu chamador em vez de retornar um erro define error.type para tool_error, também com um status ERROR.

Cada span POST de gravação também registra qual mensagem JSON-RPC seu corpo carregou, como mcp_helm.jsonrpc.message.kind (request, notification ou response). Uma notificação adiciona mcp.method.name, _OTHER para um método que o registro não lista, e uma resposta adiciona jsonrpc.request.id. O mcp-go abre um span MCP somente para as solicitações que despacha, então para notificações e para respostas de um cliente a pings do servidor, que são a maioria dos POSTs que uma sessão ociosa envia, o span HTTP é o único registro. O método e o ID de uma solicitação permanecem em seu span MCP, então uma consulta sobre eles conta cada solicitação uma vez. A captura de anotações é limitada a 64 KiB; corpos maiores não são analisados ou anotados. Spans sem gravação pulam a captura inteiramente. Esses limites afetam apenas a telemetria: o transporte ainda recebe o corpo original e erros de leitura.

Os cabeçalhos W3C traceparent / tracestate recebidos são honrados nos modos sse e http, então uma chamada de ferramenta se junta ao rastreamento do chamador em vez de iniciar um novo. O contexto de rastreamento que um cliente coloca no params._meta (SEP-414) de uma solicitação torna-se o pai do span do servidor MCP em todos os modos, stdio incluído, pois as convenções fazem do span do cliente MCP seu pai. Quando isso substitui um contexto de transporte existente, o span MCP vincula-se a esse contexto, preservando a conexão com o span HTTP mesmo entre rastreamentos diferentes. Metadados ausentes ou inválidos mantêm o pai existente sem um link extra. Sem nenhum dos dois, cada solicitação MCP no modo stdio é um span raiz.

Métricas

MétricaTipoUnidadeAtributos
mcp.server.operation.durationhistogramasmcp.method.name, gen_ai.tool.name, gen_ai.operation.name, mcp.protocol.version, network.transport, network.protocol.name, rpc.response.status_code, error.type
mcp_helm.helm.operation.durationhistogramas…helm.operation, …helm.repository.type, error.type
http.server.*de otelhttp-http.server.request.duration, http.server.request.body.size, http.server.response.body.size. Somente modos sse/http
go.*da instrumentação de runtime do OTel-Métricas de memória, GC e goroutines do Go

mcp.server.operation.duration é o histograma que as convenções semânticas do MCP definem para o lado receptor. Ele cobre cada solicitação para a qual o mcp-go abre um span, desde o recebimento até a resposta estar pronta, incluindo aquelas respondidas com um erro. Notificações não são medidas, e também não é uma mensagem que o mcp-go recusa antes desse ponto (JSON malformado, uma versão jsonrpc errada), pois nenhuma delas recebe um span.

Todos os histogramas, incluindo MCP, Helm, HTTP e histogramas de runtime, usam por padrão agregação exponencial de base 2 sobre OTLP/HTTP e OTLP/gRPC. Os buckets se adaptam aos valores registrados, com um máximo de 160 buckets por faixa positiva ou negativa e uma escala máxima de 20. As métricas usam temporalidade cumulativa por padrão: exportações repetidas retêm observações anteriores em vez de relatar apenas o intervalo mais recente. Reinicializações de processo redefinem os valores cumulativos.

As variáveis de ambiente padrão acima podem substituir qualquer um dos padrões de forma independente. Quando agregação explícita é selecionada, os histogramas de duração MCP e Helm usam os limites recomendados de 10 ms a 300 s. Garanta que seu Collector e backend aceitem histogramas exponenciais; consultas que exigem séries _bucket clássicas podem precisar de atualização.

error.type está ausente em sucesso, que é o que as convenções especificam — não filtre por um valor ok, filtre por o atributo não definido. Em mcp.server.operation.duration ele corresponde ao span: o código de erro JSON-RPC, a menos que o atributo das convenções atribua esse código ao chamador, ou tool_error para um manipulador de ferramenta que relatou a falha ao seu chamador (o mcp-go entrega isso como uma resposta bem-sucedida carregando um resultado de erro). Um manipulador de ferramenta em pânico é respondido com -32603. Em mcp_helm.helm.operation.duration ele contém o tipo de erro do Go. As taxas dos valores de contagem dos histogramas fornecem taxas de chamada, então não há contador separado.

As operações do Helm se aninham, e cada nível registra seu próprio ponto: get_latest_values envolve get_latest_version e get_chart_values, e qualquer chamada de ferramenta que omita chart_version registra get_latest_version antes da operação que foi solicitada. Filtre por mcp_helm.helm.operation em vez de somar contagens de histograma entre operações, ou uma chamada lógica é contada mais de uma vez.

Os atributos de métrica são deliberadamente de baixa cardinalidade: URLs de repositório, nomes de charts e versões de charts aparecem em spans somente, nunca em uma métrica. gen_ai.tool.name é registrado somente para ferramentas registradas e mcp.method.name recai para _OTHER, então nenhum deles carrega uma string arbitrária de um cliente. As versões de protocolo são restritas às versões suportadas pelo mcp-go. Nas métricas http.server.*, server.address e server.port relatam -httpListenAddr em vez do cabeçalho Host da solicitação, então uma sonda não autenticada variando esse cabeçalho não pode abrir uma série por valor.

Logs

Com a telemetria habilitada, os registros de log são duplicados para o exportador de logs OTLP além do stderr. Ambos os destinos honram -logLevel, então aumentá-lo mantém os registros filtrados fora do fio, bem como fora do stderr. Cada chamada de ferramenta também registra um registro INFO com o nome da ferramenta, duração e, em falha, error.type. Esse registro descreve o manipulador em vez da resposta JSON-RPC: um erro retornado é nomeado pelo seu tipo Go, uma falha relatada ao chamador é tool_error, e um pânico é _OTHER.

Cada registro emitido de um local de chamada rastreado é correlacionado com seu span, então logs, rastreamentos e métricas se alinham no backend. Os dois destinos carregam essa correlação de forma diferente: a linha do stderr recebe campos trace_id e span_id, enquanto o registro exportado recebe os campos de ID de rastreamento do próprio modelo de dados de log, que o SDK preenche a partir do contexto de emissão. Os IDs são removidos dos atributos do registro exportado para que não estejam no fio duas vezes.

Limitações

Duas coisas são deliberadamente não instrumentadas:

  • Sem spans HTTP de saída por requisição. O trabalho de saída é coberto pelos spans de cliente manuais helm.repo.index, helm.chart.download, helm.oci.pull e helm.oci.tags. Requisições OCI ainda usam contextos criados internamente pelo SDK do Helm; instrumentar essas requisições produziria spans desconectados do trace da ferramenta.
  • Requisições de stream de longa duração são excluídas de traces e métricas HTTP. A requisição GET /sse no modo sse e a requisição GET /mcp no modo http permanecem abertas durante toda a sessão do cliente. Rastreá-las produziria spans de horas e colocaria durações de sessão no histograma de latência de requisições, então ambas são filtradas. As requisições JSON-RPC transportadas por essas sessões são rastreadas normalmente.

Desligamento

Ao receber SIGTERM ou SIGINT, o servidor para de aceitar novo trabalho, drena requisições em andamento dentro de 10 segundos e então descarrega telemetria em buffer dentro de 5, para que um cliente que nunca desconecta ou um coletor que nunca responde não possa manter o processo vivo. Os orçamentos são separados de propósito: um dreno que demora não pode gastar o tempo que o descarregamento precisa. Um segundo sinal encerra imediatamente.

Dê espaço ao processo para terminar: defina terminationGracePeriodSeconds (ou docker stop -t) para pelo menos 20 segundos, ou os spans e registros de log em buffer no momento do sinal serão perdidos.

Uma transporte que falha ao iniciar — uma porta já em uso, um endereço de escuta inutilizável — é registrado como fatal e sai com status 1.

Roadmap

  • Instrumentação OpenTelemetry (traces, métricas e logs via OTLP)
  • Adicionar mais ferramentas
    • Listar todos os charts em um repositório
    • Listar todas as versões de um chart
    • Obter a versão mais recente do chart
    • Obter valores para o chart
    • Obter valores para a versão mais recente do chart
    • Extrair conteúdo completo do chart
    • Extrair charts dependentes do Charts.yaml
    • Extrair imagens usadas no chart
  • Suporte a registries OCI
    • Baixar charts de registries OCI
    • Listar tags/versões de registries OCI
    • Suporte a autenticação via credenciais Docker
  • Suporte ao uso de repositórios HTTP privados
    • Adicionar uma forma de fornecer credenciais para autenticação básica HTTP