Scouter MCP

Consulte o Scouter APM (objetos, contadores, transações XLog) via stdio através de um coletor Scouter.

Documentação

scouter-mcp

Para documentação em coreano, consulte README.ko.md.

Um servidor MCP stdio que se conecta diretamente a um Scouter Collector via TCP e consulta XLogs, contadores e objetos. Seu objetivo é permitir que uma IA explore rapidamente métricas do Scouter e diagnostique causas raiz. Cada resultado carrega txid / gxid / objName / endTimeIso, que você pode usar como chaves para análise cruzada com outras ferramentas de observabilidade, como OpenSearch ou Datadog.

Arquitetura

Java 17. Reutiliza scouter-common e porta as classes scouter.webapp net/server para o pacote scouter.mcp.client. O MCP usa o transporte stdio do Java SDK 2.0.0. Todas as operações contra o Collector são somente leitura.

Build

./gradlew shadowJar
# output: build/libs/scouter-mcp-<version>-all.jar

O bundle .mcpb é produzido apenas pelo CI de release (que encapsula este jar); builds locais apenas geram o jar.

Registro (Claude Code, Claude Desktop, ...)

Para um único collector, instale o bundle .mcpb a partir do GitHub Release para uma configuração em um clique — ou copie .mcp.json.example, aponte-o para o fat jar (baixado do release ou compilado localmente) e preencha as credenciais. Para múltiplos collectors, consulte Múltiplos collectors.

Variável de ambienteDescrição
SCOUTER_COLLECTOR_HOSTHost do collector
SCOUTER_COLLECTOR_PORTPorta TCP do collector (padrão 6100)
SCOUTER_USERUsuário de login
SCOUTER_PASSWORDSenha de login
SCOUTER_TZFuso horário (ex.: Asia/Seoul)
SCOUTER_LOCALEIdioma das mensagens ao usuário: en ou ko. Se não definido, derivado do padrão da JVM (coreano apenas quando o idioma da JVM for coreano; caso contrário, inglês)
SCOUTER_INCLUDE_BIND_PARAMSInterruptor de segurança do operador para parâmetros de bind SQL em get_xlog_detail (padrão true). Defina como false para remover parâmetros de bind no lado do servidor, independentemente do argumento por chamada — um LLM não pode reativá-los. Use quando os valores de bind puderem conter PII.

Múltiplos collectors

O release oficial inclui um bundle .mcpb (instalação em um clique, um único collector) além do fat jar autônomo. Um .mcpb define exatamente um servidor com um conjunto de credenciais, portanto não pode registrar dois collectors ao mesmo tempo. Para múltiplos collectors — que geralmente diferem em todo o conjunto de conexão (host/porta e usuário/senha) — use o jar diretamente e adicione uma entrada por collector:

  1. Baixe scouter-mcp-<version>-all.jar do GitHub Release.
  2. Adicione uma entrada mcpServers por collector à configuração do seu cliente (.mcp.json / claude_desktop_config.json), todas apontando para o mesmo jar, cada uma com seu próprio conjunto de variáveis de ambiente. Isso mantém cada credencial isolada:
{
  "mcpServers": {
    "scouter-prod": {
      "command": "java",
      "args": ["-jar", "/ABSOLUTE/PATH/scouter-mcp-<version>-all.jar"],
      "env": {
        "SCOUTER_COLLECTOR_HOST": "prod-collector", "SCOUTER_COLLECTOR_PORT": "6100",
        "SCOUTER_USER": "prod-user", "SCOUTER_PASSWORD": "***", "SCOUTER_TZ": "Asia/Seoul"
      }
    },
    "scouter-stg": {
      "command": "java",
      "args": ["-jar", "/ABSOLUTE/PATH/scouter-mcp-<version>-all.jar"],
      "env": {
        "SCOUTER_COLLECTOR_HOST": "stg-collector", "SCOUTER_COLLECTOR_PORT": "6100",
        "SCOUTER_USER": "stg-user", "SCOUTER_PASSWORD": "***", "SCOUTER_TZ": "Asia/Seoul"
      }
    }
  }
}

A IA então orquestra entre os collectors.

Ferramentas (14)

NomeFinalidadeEntradas principais
list_objectsListar objetos/agentesobjType?, nameLike? (insensível a maiúsculas/minúsculas)
search_xlogPesquisar XLogs (latência/erros)from, to, objNameLike?, objHash?, service?, login?, ip?, desc?, minElapsedMs?, onlyError?, limit? (padrão 20, máximo 200)
get_service_summaryAgregado por serviço (contagem/média/máx/p95/taxaDeErros), top 50from, to, mesmos filtros de search_xlog
get_summaryEstatísticas diárias pré-agregadas do collector (top-50 SQL/serviço/erro/... — sem varredura)category (service/sql/apiCall/ip/userAgent/error/alert), from, to (até 31 dias), objType?, objNameLike?, objHash?
get_xlog_detailDetalhe do XLog (SQL/parâmetros de bind)txid, date?/at?, includeBindParams? (padrão true)
get_xlog_by_gxidGrupo de transações distribuídasgxid, date?/at?
get_counterSérie temporal de contadores (mesmo dia, resolução total)objNameLike|objHashes|objType, counter, from, to
get_counter_statEstatísticas de contadores de longo alcance (resolução de 5 min, até 31 dias)objNameLike|objHashes|objType, counter, from, to
list_countersContadores disponíveis para um objTypeobjType
list_alertsAlertas passados do collectorfrom, to, level?, object?, key?, limit?
get_active_servicesServiços em execução agoraobjNameLike|objType|objHash
list_threadsLista de threads da JVM (histograma de estados + top 50 por cpu)objNameLike|objHash (máximo 5 instâncias ativas)
get_thread_detailThread ao vivo de uma transação ATIVA (stack/dono do lock/SQL atual)txid (obrigatório, ativo), id?, objNameLike|objHash
get_object_envPropriedades do sistema da JVM do agente (segredos mascarados)objNameLike|objHash, keyLike?

Segmentação difusa (objNameLike)

Os usuários digitam fragmentos de nomes de aplicativos ("shop-order-api"), mas os objNames reais incorporam o nome do pod k8s (/shop-order-api-deployment-5f4b8c7d9-abcde/shop-order-api1), então o objHash muda a cada deploy e um aplicativo abrange várias instâncias. objNameLike resolve isso: um fragmento insensível a maiúsculas/minúsculas é resolvido para todas as instâncias correspondentes (ativas primeiro, limitado a 20) e consultado entre elas — sem necessidade de objHash, nunca. Para pesquisa/resumo de XLog, a resolução também une o banco de dados diário de objetos do collector, para que pods substituídos por um deploy durante a janela consultada ainda sejam encontrados. Se nada corresponder, o erro é NOT_FOUND com uma dica candidates listando os objNames reais para que o chamador possa se autocorrigir em uma etapa.

Consultas de serviço imprecisas

Os nomes de serviço do Scouter parecem /api/order/.../search-order-info-grade<POST>, mas os usuários digitam "GET orderDetail" ou "order info grade". O filtro service normaliza essa entrada: um método HTTP é extraído de qualquer posição (GET x, x POST, <POST> colado), palavras separadas por espaços em branco recaem no token mais longo no lado do servidor, e padrões * explícitos passam inalterados. A correspondência no lado do servidor ainda é sensível a maiúsculas/minúsculas — portanto, quando um padrão não corresponde a nada, a mesma janela é reexaminada (limitada) sem o filtro de serviço e os nomes de serviço reais que correspondem aos tokens da consulta sem diferenciar maiúsculas/minúsculas são retornados como serviceCandidates, ordenados por tráfego. Uma nova tentativa com um nome exato resolve o problema.

service/login/ip/desc usam correspondência de substring por padrão (StrMatch no lado do servidor), então um token curto como search-order-info-grade corresponde a /api/order/ext/order-info/search-order-info-grade<POST>. objNameLike/login/ip/desc contam como filtros no lado do servidor, portanto relaxam o limite de janela sem filtro de 5 minutos. list_counters também aceita objNameLike e deriva o objType, então os usuários nunca precisam conhecer a taxonomia de tipos do Scouter.

Todas as ferramentas são anunciadas com readOnlyHint. Um prompt MCP diagnose_root_cause expõe a ordem recomendada de ferramentas para investigações de latência/erros.

Política de segurança de recursos/tokens

O Scouter de produção pode produzir centenas de milhares de XLogs em cinco minutos, então search_xlog aplica proteções (consulte scouter.mcp.policy.Limits):

  • Durante o streaming, ele para assim que o limit ou o limite de varredura (5.000 pacotes examinados) é atingido e fecha o socket, o que também interrompe a varredura/transferência do Collector — limitando a carga do servidor, a rede e o heap do MCP juntos.
  • Sem um filtro service ou objHash, apenas janelas de até 5 minutos são permitidas; o limite absoluto de janela é de 24 horas.
  • limit tem padrão 20 e é limitado a 200. Os resultados incluem truncated/scanCapReached e um hint para que o chamador possa restringir filtros em vez de buscar novamente.
  • get_service_summary não retém linhas (apenas contadores por serviço), portanto usa um limite de varredura maior (200.000) para cobrir janelas mais amplas de forma econômica; também reporta scanCapReached/examined.
  • get_counter limita o fan-out por objType a 20 instâncias e reduz a amostragem de séries longas com um esquema de min/máx que preserva picos/quedas (resumo min/max/avg calculado a partir da série completa).
  • Janelas que cruzam a meia-noite são divididas por dia calendário (o collector particiona XLogs/contadores/alertas por dia), então nenhum dado é perdido em nenhum dos lados do limite.
  • Orçamentos de texto de resposta: texto SQL cortado em 1.500 caracteres, mensagens de erro em 500, stack traces de threads em 4.000, valores de ambiente em 500 — cada um com um marcador de truncamento carregando o comprimento original. Etapas de perfil get_xlog_detail são limitadas a 150, sinalizadas via totalSteps/stepsTruncated.
  • Uma única solicitação pode fazer fan-out para no máximo 40 idas e voltas ao collector (instâncias x segmentos de dia). Quando filtros no lado do cliente (minElapsedMs/onlyError) descartam mais de 99% das linhas varridas, uma dica de baixa seletividade orienta o modelo para filtros no lado do servidor ou get_summary.
  • get_summary/get_counter_stat leem os dados diários pré-agregados do collector (sem varredura), limitados a 31 dias; o resumo retorna as 50 principais linhas por categoria. list_threads limita a 5 instâncias ativas e 50 linhas de thread cada (o histograma de estados sempre cobre todas as threads).
  • Telemetria por solicitação (passes/examined/kept/tookMs) é registrada no stderr como linhas key=value estruturadas para análise de carga posterior.

Internacionalização

Apenas a saída dinâmica voltada ao usuário (mensagens de erro de ferramentas, dicas de resultados, notas) é localizada, em inglês e coreano, via messages.properties / messages_ko.properties. Descrições estáticas de schema/ferramentas e logs estruturados de stderr (key=value) permanecem em inglês para um contrato estável e análise de logs.

Notas de segurança

  • Somente leitura contra o Collector (nenhum comando de escrita é exposto).
  • Credenciais são injetadas apenas via variáveis de ambiente (nunca em arquivos ou argumentos como texto simples). Prefira uma conta Scouter de privilégio mínimo / somente leitura.
  • O transporte é TCP sem criptografia (o protocolo Scouter não tem TLS): o digest SHA-256 da senha, o token de sessão e todos os dados de XLog/contador atravessam a rede sem criptografia. Execute apenas dentro de uma rede confiável, ou use túnel SSH/VPN. Não exponha a porta do collector na internet pública.
  • Parâmetros de bind get_xlog_detail podem conter PII. Defina SCOUTER_INCLUDE_BIND_PARAMS=false para removê-los no lado do servidor (o LLM não pode reativá-los). Consulte a tabela de variáveis de ambiente acima. Os valores de bind ao vivo de get_thread_detail (SQLActiveBindVar) obedecem ao mesmo interruptor de segurança.
  • get_object_env incondicionalmente mascara valores de chaves que correspondem a password/secret/token/credential/ private — uma política no lado do servidor da qual o LLM não pode optar por sair.
  • stdout é reservado para JSON-RPC, então todos os logs vão apenas para stderr.

Licença / Aviso

O pacote scouter.mcp.client é portado do código cliente do Scouter v2.20.0 (Apache License 2.0). Consulte NOTICE para detalhes.

Limitações conhecidas

  1. search_xlog/get_service_summary minElapsedMs/onlyError/limit são aplicados no lado do cliente porque o Collector não tem parâmetros nativos para eles. truncated=true é uma heurística (contagem retornada == limite) e pode ser um falso positivo.
  2. Em expiração de sessão (INVALID_SESSION), o cliente faz login novamente uma vez e tenta a solicitação; uma segunda falha aparece como SCOUTER_AUTH_FAILED (sem loop infinito de tentativas). O daemon de atualização de delta de tempo de 2 segundos upstream ainda não foi portado, então processos de longa duração podem sofrer pequenos desvios para consultas relativas em tempo real. Consultas de época absoluta (históricas) não são afetadas.
  3. list_alerts/get_active_services foram portados do protocolo upstream e validados contra um collector via os testes de fumaça (SmokeIT); a cobertura de campos pode variar conforme a versão do collector.