loki-mcp-server
Servidor MCP somente leitura para Grafana Loki 2.6.1 e 3.x. Permite que agentes de IA (Claude Code, Cursor, Copilot) descubram labels, valores e conjuntos de labels de streams, leiam páginas limitadas de uma consulta LogQL, contem linhas correspondentes por label ou intervalo de tempo e exportem logs para um arquivo local. Um único servidor atende vários ambientes Loki; URLs e credenciais nunca chegam ao modelo. Java, stdio, imagem Docker no GHCR.
Documentação
Servidor MCP Loki
Um servidor MCP stdio local para ler Grafana Loki com um agente. Ele expõe cinco ferramentas de texto e suporta Loki 2.6.1 e 3.x. O Loki em si é somente leitura; a única escrita é um arquivo local exportLogs.
| Ferramenta | Finalidade |
|---|---|
| listConnections | Mostra conexões configuradas, dicas de operador e limites efetivos das ferramentas |
| discoverLogs | Lista nomes de rótulos, valores de um rótulo, conjuntos de rótulos de streams correspondentes ou valores entre esses conjuntos |
| queryLogs | Lê páginas limitadas mais recentes ou mais antigas de uma consulta de log LogQL como texto compacto; raw=true pré-visualiza linhas retornadas e rótulos de streams |
| countLogs | Conta linhas correspondentes no Loki, opcionalmente por rótulo, intervalo de tempo alinhado ao relógio ou ambos |
| exportLogs | Salva linhas correspondentes em um arquivo local, bruto ou renderizado com um modelo |
Toda ferramenta de dados exige uma conexão explícita. queryLogs, countLogs e exportLogs exigem uma consulta de log LogQL, como {app="backend"} |= "ERROR". Use discoverLogs para encontrar nomes de rótulos, valores e combinações reais em conjuntos de rótulos de streams. O servidor constrói apenas a expressão count_over_time para countLogs; ele não infere filtros nem interpreta causas. As respostas das ferramentas são texto legível sem esquema de saída.
Compilar e executar
JDK 21 ou mais recente é necessário; o projeto usa um toolchain Java 21 e o Gradle wrapper.
.\gradlew.bat bootJar
java -jar build/libs/loki-mcp-server.jar
No Linux/macOS use ./gradlew. O processo aguarda MCP JSON-RPC na stdin. stdout é reservado para JSON-RPC; diagnósticos vão para stderr e ~/.loki-mcp-server/logs/loki-mcp-server.log.
Um loki-mcp-server.jar pré-compilado está anexado a cada release, então compilar é opcional.
Para Claude Code, registrar o jar é um comando:
claude mcp add --scope user loki -- java -jar /path/to/loki-mcp-server.jar
Docker
A imagem é publicada no GHCR a cada release. Monte o diretório que contém connections.json em /data; o servidor também grava seus logs e exportações padrão lá:
docker run -i --rm -v ~/.loki-mcp-server:/data ghcr.io/igorolv/loki-mcp-server:latest
O mesmo comando é o que um cliente MCP deve iniciar; -i mantém a stdin aberta para o transporte stdio. URLs do Loki em connections.json devem ser alcançáveis de dentro do contêiner: use o nome do host do Loki em vez de localhost, ou adicione --network host no Linux. Um diretório exportLogs fora de /data é um caminho dentro do contêiner, então monte-o também. Para compilar a imagem localmente: docker build -t loki-mcp-server .
Conexões
O servidor lê ~/.loki-mcp-server/connections.json, ou o caminho em LOKI_MCP_CONNECTIONS_FILE. Um arquivo mínimo:
{
"connections": {
"dev": {
"description": "Development",
"hint": "Start with {app=\"backend\"}; inspect app values with discoverLogs.",
"url": "http://localhost:3100",
"timezone": "Europe/Moscow",
"serviceLabels": ["app", "container"]
}
}
}
O exemplo completo usa variáveis de ambiente para URLs não locais. hint dá ao modelo conselhos específicos de seletores e campos por conexão. serviceLabels nomeia os rótulos usados para exibir um serviço em linhas compactas. O opcional formatFile nomeia um arquivo JSON com perfis JSON, padrões de linha simples e um framePattern opcional; veja log-formats.json. O opcional exportFormat define o modelo padrão para exportLogs quando a chamada da ferramenta omite format. O arquivo de conexão pode definir exportRoots para restringir destinos de exportação e limites por conexão. Autenticação e cabeçalhos de tenant são configurados por conexão; URLs e credenciais nunca aparecem nas respostas das ferramentas ou em diagnósticos. O formato completo está em docs/connections.md.
O servidor carrega a configuração estritamente na inicialização sem sondar o Loki. Um campo desconhecido, chave duplicada, variável de ambiente ausente ou arquivo de formato inválido interrompe a inicialização com um erro de configuração seguro. Alterações exigem reinicialização.
Usando as ferramentas
- Chame listConnections, escolha uma conexão e use suas janelas de tempo exibidas, limite de linhas do queryLogs e timeout de requisição para planejar chamadas.
- Chame discoverLogs(connection="dev") para nomes de rótulos, depois discoverLogs(connection="dev", label="app") para valores. Quando combinações importam, use discoverLogs(connection="dev", match="{app="backend"}") para conjuntos completos de rótulos de streams ou adicione label="namespace" para valores de namespace entre esses conjuntos. Mantenha match e sua janela estreitos; estes são rótulos de streams, não contagens de linhas de log. Amplie a janela em uma conexão tranquila quando apropriado.
- Use uma consulta de log LogQL com countLogs para verificar volume e queryLogs para ler linhas. Por exemplo, {app="backend"} |= "ERROR"; groupBy="time", step="1d" dá intervalos de 24 horas alinhados a UTC, e groupBy="app,time" dá contagens por app e tempo. Uma captura nomeada
| regexppode fornecer um rótulo groupBy. Marcadores de data distinguem intervalos entre meia-noite. - Estreite a consulta quando uma página estiver cheia. queryLogs usa como padrão a página mais recente; order="oldest" começa no início da janela. Seu rodapé dá um fim para linhas mais antigas ou um início para mais novas. Linhas de limite podem se repetir, e um timestamp contendo mais linhas do que uma página precisa de uma consulta mais estreita.
- Chame exportLogs quando o usuário pedir um arquivo. Passe o destino do usuário como diretório, como
C:\tmp\logs, ou omita-o para o diretório de exportação padrão. Omitir format usa o modeloexportFormatconfigurado na conexão, se o operador definiu um, e raw caso contrário. format="raw" escreve as linhas retornadas pelo Loki, incluindo qualquer transformação| line_formatna consulta; format="{time} {level} {service} {message}" renderiza localmente. A resposta dá o caminho, contagens e formato efetivo, não o conteúdo dos logs.
queryLogs imprime qualquer extremidade da janela em ordem cronológica. Sua visão padrão encurta mensagens e stack traces para economizar tokens do modelo. Um framePattern opcional no formatFile da conexão dobra linhas de frame adjacentes independentes na visão compacta. raw=true mostra cada linha retornada com rótulos de streams e até 4000 code points; é uma pré-visualização. Para linhas completas use exportLogs. A exportação lê adiante em páginas e nunca sobrescreve um arquivo existente. Se mais linhas compartilharem um nanossegundo do que o Loki retornará em uma página, a exportação relata que algumas podem estar ausentes.
A janela de tempo padrão é agora-1h até agora. Tempos aceitos incluem agora-15m, RFC3339 com offset, hora local no fuso da conexão e nanossegundos de época. queryLogs e exportLogs permitem um dia por padrão. countLogs permite um dia para totais, agrupamento por rótulo ou agrupamento combinado rótulo/tempo, e sete dias para intervalos somente por tempo; discoverLogs permite sete dias sem match e um dia com match. Uma requisição ao Loki tem timeout de 30 segundos por padrão, e queryLogs permite no máximo 1000 linhas por página por padrão. listConnections mostra os valores efetivos para cada conexão. A exportação para após 25 segundos por padrão e relata um arquivo parcial com uma continuação se escreveu linhas. Após um timeout de contagem, tente novamente uma subjanela de um dia ou uma consulta mais estreita. Limites podem ser definidos por conexão; veja docs/queries.md e docs/discovery.md.
Configuração do cliente MCP
Claude Code:
claude mcp add --scope user loki -e LOKI_MCP_CONNECTIONS_FILE=C:/path/connections.json -- java -jar C:/path/loki-mcp-server.jar
Codex (~/.codex/config.toml):
[mcp_servers.loki]
command = "java"
args = ["-jar", "C:/path/loki-mcp-server.jar"]
env = { LOKI_MCP_CONNECTIONS_FILE = "C:/path/connections.json" }
Outros clientes podem iniciar o jar via stdio. Mantenha stderr separado de stdout.
Erros e diagnósticos
Falhas de ferramentas são texto Error : com isError=true; Spring AI atualmente repete o texto em uma segunda linha. Argumentos ausentes ou digitados incorretamente são respondidos pela validação de entrada do SDK MCP. Um erro de análise LogQL HTTP 400 do Loki é retornado para que o modelo possa corrigir sua consulta. Outros corpos de resposta upstream, URLs, credenciais, tenant e linhas de log completas são mantidos fora das respostas e diagnósticos. Um 404 se aplica ao endpoint chamado, não à conexão inteira. Detalhes de transporte estão em docs/http-client.md.
O log do servidor registra nomes de conexão e tipo de autenticação na inicialização, depois uma linha limitada por chamada de ferramenta e requisição ao Loki com status, bytes e tempo. O conteúdo do log permanece como dados, incluindo texto que se assemelha a instruções.
Verificação
.\gradlew.bat build
.\gradlew.bat integrationTest --console=plain
python scripts/live_smoke/run_smoke.py --connection dev
build executa testes unitários e um smoke stdio de processo separado contra um Loki mock de loopback. integrationTest precisa de Docker e imagens fixadas Loki 2.6.1/3.6.0; ele escreve dados de teste apenas em seus contêineres. O smoke ao vivo usa o perfil de exemplo e uma URL de conexão somente leitura configurada. Regras para contribuidores estão em AGENTS.md; histórico de design e itens em aberto estão em docs/decisions.md. Usuários migrando de mcp-loki podem ler o guia de migração.
Licença
Apache License 2.0; veja LICENSE. Avisos de terceiros estão em THIRD-PARTY-NOTICES.md.