elasticsearch-investigation-mcp
Read-only MCP server that converts Elasticsearch logs into citable evidence for AI agents, offering deterministic log summarization and search tools.
README
Elasticsearch Investigation MCP
Elasticsearch에 쌓인 로그를 n8n AI Agent가 인용할 수 있는 증거로 바꿔 주는 읽기 전용 MCP 서버입니다. Agent가 호스트·시간 범위·조건을 결정하고, 이 서버는 조회와 파싱, 집계를 결정론적으로 수행합니다.
Zabbix Investigation MCP와 짝을 이룹니다. 메트릭이 "언제 이상해졌는가"를 말한다면 로그는 "무엇이 실패했는가"를 말합니다. 두 서버가 같은 호스트 이름을 쓰기 때문에 한 조사 안에서 나란히 놓일 수 있습니다.
원본이 파싱되어 있지 않다는 전제
이 서버가 읽는 인덱스에는 로그 레벨·서비스·메시지가 필드로 분리되어 있지
않습니다. 수집기가 원문 한 줄을 message에 통째로 넣습니다. 따라서
- 레벨은 필터가 아니라 파싱 결과입니다. Elasticsearch로는 "그 단어가 들어간
줄"까지만 좁히고, 그중 진짜 그 레벨인 줄은 이 서버가 앞부분을 해석해서
가려냅니다. 본문에
ERROR를 인용한 INFO 줄은 INFO로 셉니다. - 응답은 얼마나 이해했는지를 함께 보고합니다.
data_quality.formats와unlevelled_lines가 그것입니다. 파싱률을 숨긴 채 정밀해 보이는 숫자만 주면 신뢰할 수 없는 근거가 됩니다.
인식하는 형식은 Spring Boot, 날짜 시각 LEVEL 본문, syslog 세 가지이고, 어느
쪽도 아니면 unrecognised로 표시한 뒤 레벨 단어만 찾아봅니다.
제공 도구
summarize_logs — 먼저 부르는 도구
한 호스트가 어떤 구간에 남긴 로그 전체가 무엇을 말하는지 요약합니다. 줄 자체는 반환하지 않습니다. 바쁜 호스트는 시간당 수천 줄을 쓰기 때문에, 이 도구는 "어느 분, 어느 메시지를 봐야 하는가"까지만 알려 줍니다.
by_level,by_service— 레벨/서비스별 건수volume_over_time— 구간을 10개 구획으로 나눈 분포. Elasticsearch가 전체 문서를 대상으로 센 값이라 아래의 표본이 잘려도 정확합니다. 80배 급증 같은 것은 여기서 보입니다.repeated_messages— 변하는 부분(숫자·IP·16진수·따옴표 문자열·스택 프레임)을 치환해 같은 모양끼리 묶은 목록. 문제 레벨이 위로 옵니다.analysed,analysed_window,data_quality.sampled_fraction— 파싱 통계가 실제로 어디까지를 설명하는지. 한 시간을 물었는데 표본이 앞 17분이었다면 그 사실이 응답에 있어야 합니다.
search_logs — 요약이 지목한 줄을 읽는 도구
level·contains·services로 좁혀서 실제 줄을 가져옵니다. 최신순입니다. 긴
메시지는 잘라내고 잘랐다고 표시합니다.
반환되는 message는 원문 전체가 아니라 파싱된 본문입니다. Spring 접두부
118자(타임스탬프·레벨·pid·서비스·스레드·로거)는 이미 각각의 필드로 따로
돌려주므로, 그것까지 문자 예산에 넣으면 스택 트레이스가 시작되기도 전에 잘립니다.
쓰기 도구, 인덱스 변경, 클러스터 설정 도구는 제공하지 않습니다.
환경 변수
Copy-Item .env.example .env
필수 설정:
ES_URL: Elasticsearch 주소 (예:http://elasticsearch.example.com:9200)ES_API_KEY: 로그 인덱스에read,view_index_metadata만 가진 API Key. Base64 인코딩된id:secret형태 그대로 넣습니다.ES_MCP_AUTH_TOKEN: MCP 클라이언트가 사용할 Bearer Token
[Convert]::ToHexString(
[Security.Cryptography.RandomNumberGenerator]::GetBytes(32)
).ToLower()
필드 이름
ES_HOST_FIELD(기본host.name) — Zabbix가 부르는 이름과 같은 값이 들어 있어야 합니다. 다르면 로그가 옆에 놓일 메트릭을 찾지 못합니다.ES_TIMESTAMP_FIELD(기본@timestamp)ES_MESSAGE_FIELD(기본message)ES_SERVICE_FIELD(기본service.name)
조회 정책
ES_ALLOWED_INDEX_PATTERNS(기본값 없음 = API Key가 허용하는 전부). API Key도 범위를 정하지만 키는 한 번 크게 발급되므로, 이 목록은 키를 다시 발급하지 않고 배포 단위로 좁힐 수 있는 경계입니다.*만 와일드카드로 동작하고.은 문자 그대로 취급합니다.INVESTIGATION_MAX_WINDOW_HOURS(기본26) — 한 번의 호출이 덮을 수 있는 구간. 보존 기간이 무제한이면 이 값이 유일한 제동 장치입니다. 호스트 한 대가 이미 시간당 약 4천 줄을 씁니다. 26은 하루치 조회에 시간대 차이만큼의 여유를 더한 값입니다.INVESTIGATION_MAX_FETCH_DOCUMENTS(기본10000) — 답 하나를 만들려고 Elasticsearch에서 끌어오는 문서 수. 응답 크기가 아니라 작업량의 상한입니다.INVESTIGATION_MAX_RETURNED_LINES(기본100),INVESTIGATION_MAX_MESSAGE_CHARS(기본600),INVESTIGATION_MAX_SHAPES(기본25) — 모델이 실제로 값을 치르는 부분.INVESTIGATION_MAX_FUTURE_HOURS(기본2) — 미래 구간은 아무것도 반환하지 않는데, 그것이 "조용했다"로 읽히면 안 되므로 오류로 처리합니다.
Docker 실행
docker compose up -d --build
docker compose ps
Invoke-RestMethod http://127.0.0.1:3001/healthz
기본 엔드포인트:
- MCP:
http://<host>:3001/mcp - 상태 확인:
http://<host>:3001/healthz
Authorization: Bearer <ES_MCP_AUTH_TOKEN>
Zabbix Investigation MCP와 같은 머신에 올릴 수 있습니다. compose project 이름과
게시 포트가 다르므로 서로 간섭하지 않습니다 (MCP_PUBLISHED_PORT=3001).
컨테이너 내부 포트는 양쪽 모두 3000입니다.
네트워크 노출 제한
컨테이너 포트가 게시되는 호스트 인터페이스는 MCP_BIND_ADDRESS가 정합니다.
MCP_BIND_ADDRESS=10.0.0.10 # 이 머신의 사설 IP
값을 지정하지 않으면 127.0.0.1로 게시되므로, 설정을 빠뜨려도 공인
인터페이스에 열리지 않습니다.
MCP_HOST와 혼동하지 않아야 합니다. MCP_HOST는 프로세스 자체의 바인드
주소이고 docker compose에서는 컨테이너 내부 기준 0.0.0.0으로 고정됩니다.
호스트 노출을 실제로 통제하는 값은 MCP_BIND_ADDRESS입니다.
Docker는 자신의 forwarding 규칙을 ufw보다 앞에 삽입하므로, 0.0.0.0으로
게시한 포트는 호스트 방화벽으로 막히지 않습니다. 방화벽에 의존하지 말고 바인드
주소를 지정하십시오.
적용 결과는 실행 전에 확인할 수 있습니다.
docker compose config
MCP_ALLOWED_HOSTS는 소스 IP가 아니라 요청의 Host 헤더를 검사합니다. DNS
rebinding 방어용이며 네트워크 접근 제어를 대신하지 않습니다.
로컬 개발
요구 사항은 Node.js 20 이상입니다.
npm ci
npm run typecheck
npm test
npm run build
npm run dev
Elasticsearch가 사설망에 있으면 터널을 열고 붙습니다.
ssh -N -L 19200:<elasticsearch-host>:9200 <jump-host>
저장소 구조
.
├── src/
│ ├── log-parse.ts 원문 한 줄에서 레벨·서비스·본문을 읽어내는 곳
│ ├── policies.ts 구간·인덱스·건수 상한
│ ├── es-client.ts Elasticsearch REST 호출
│ ├── es-service.ts 두 도구의 실제 동작
│ └── register-tools.ts
├── tests/
├── Dockerfile
├── docker-compose.yml
├── package.json
└── .env.example
클라이언트의 ES_MCP_URL은 이 서버의 /mcp 주소를 가리켜야 하며, n8n HTTP
Bearer Auth credential에는 동일한 ES_MCP_AUTH_TOKEN을 입력합니다.
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
E2B
Using MCP to run code via e2b.
Neon Database
MCP server for interacting with Neon Management API and databases
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.