Elastic MCP Server

Elastic MCP Server

A read-only MCP server that gives AI assistants natural language access to Elasticsearch/Kibana logs for querying and analysis.

Category
Visit Server

README

Elastic MCP Server

A Model Context Protocol (MCP) server that gives AI assistants read-only access to your Elasticsearch/Kibana logs. Ask questions in natural language and get answers backed by real log data.

Works with Claude Code, Claude Desktop, and any MCP-compatible client. Your project can be in any language — Python, Java, Go, Node.js, etc. This server runs independently.

<p align="center"> <img src="https://img.shields.io/badge/MCP-compatible-blue" alt="MCP Compatible" /> <img src="https://img.shields.io/badge/node-%3E%3D18-green" alt="Node >= 18" /> <img src="https://img.shields.io/badge/license-MIT-brightgreen" alt="MIT License" /> </p>

How It Works

Your project (any language)     elastic-mcp-server           Kibana / Elasticsearch
┌───────────────────┐          ┌──────────────────┐          ┌──────────────────┐
│  Claude Code or   │  stdio   │                  │  HTTPS   │                  │
│  Claude Desktop   │────MCP──>│  Translates to   │────────->│  Executes query  │
│                   │<─────────│  Kibana queries  │<─────────│  Returns results │
└───────────────────┘          └──────────────────┘          └──────────────────┘

The server runs as a standalone Node.js process alongside your project. Claude spawns it, communicates via stdio, and uses it to search your logs. It doesn't depend on your project's language, framework, or build system. All requests are read-only.

Requirements

  • Node.js >= 18 or Docker (only for running this MCP server — your project can use any language)

Quick Start

Option A: Node.js

1. Clone and build

git clone https://github.com/vanovarderesyan/elastic-mcp-server.git
cd elastic-mcp-server
npm install
npm run build

This creates the compiled server at dist/main.js.

2. Configure

Add the MCP server to your AI assistant. You need:

  • The absolute path to dist/main.js where you cloned this repo
  • Your Kibana URL and credentials

Claude Code — create or edit .mcp.json in any project directory:

{
  "mcpServers": {
    "elasticsearch": {
      "command": "node",
      "args": ["/home/john/elastic-mcp-server/dist/main.js"],
      "env": {
        "ELASTIC_NODES": "https://kibana.example.com",
        "ELASTIC_USERNAME": "your-username",
        "ELASTIC_PASSWORD": "your-password"
      }
    }
  }
}

Claude Desktop — edit the config file:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
  • Windows: %APPDATA%\Claude\claude_desktop_config.json
{
  "mcpServers": {
    "elasticsearch": {
      "command": "node",
      "args": ["/home/john/elastic-mcp-server/dist/main.js"],
      "env": {
        "ELASTIC_NODES": "https://kibana.example.com",
        "ELASTIC_USERNAME": "your-username",
        "ELASTIC_PASSWORD": "your-password"
      }
    }
  }
}

Note: Replace /home/john/elastic-mcp-server with the actual path where you cloned this repo.

Option B: Docker

No Node.js required — just Docker.

1. Build the image

git clone https://github.com/vanovarderesyan/elastic-mcp-server.git
cd elastic-mcp-server
docker build -t elastic-mcp-server .

2. Configure

Claude Code — create or edit .mcp.json:

{
  "mcpServers": {
    "elasticsearch": {
      "command": "docker",
      "args": [
        "run", "-i", "--rm",
        "-e", "ELASTIC_NODES=https://kibana.example.com",
        "-e", "ELASTIC_USERNAME=your-username",
        "-e", "ELASTIC_PASSWORD=your-password",
        "elastic-mcp-server"
      ]
    }
  }
}

Claude Desktop — same structure in your claude_desktop_config.json.

Why -i and no -t? MCP communicates over stdin/stdout using structured JSON. The -i flag keeps stdin open for the MCP protocol. The -t flag (TTY) is not needed and would interfere with the JSON stream.

Cloudflare Zero Trust with Docker

If your Kibana is behind Cloudflare Access, the container needs access to your host's Cloudflare tokens. Mount the ~/.cloudflared directory as a read-only volume:

{
  "mcpServers": {
    "elasticsearch": {
      "command": "docker",
      "args": [
        "run", "-i", "--rm",
        "-v", "/home/john/.cloudflared:/root/.cloudflared:ro",
        "-e", "ELASTIC_NODES=https://kibana.example.com",
        "-e", "ELASTIC_USERNAME=your-username",
        "-e", "ELASTIC_PASSWORD=your-password",
        "elastic-mcp-server"
      ]
    }
  }
}

Replace /home/john/.cloudflared with your actual home directory path (e.g., /Users/jane/.cloudflared on macOS).

You must authenticate on your host machine first:

cloudflared access login https://kibana.example.com

The container reads the cached token from the mounted volume. When the token expires, re-run cloudflared access login on your host — the container picks up the new token automatically.

Alternatively, pass a token directly via environment variable:

"-e", "CF_ACCESS_TOKEN=eyJhbGciOi..."

3. Discover your indices

Every Elasticsearch setup is different. Your indices might be named filebeat-*, logstash-*, production-api-*, staging-*, or something else entirely. The first thing to do after setup is ask Claude to list what's available:

List all data views

This shows you the actual index patterns in your Kibana. Use those names when searching.

Important: By default, the index parameter is *, which searches all environments (production, staging, dev, etc.). Always specify the index when searching to avoid mixing logs from different environments:

Search for errors in production-api-* from the last hour
Show me logs from staging-auth-service-* today
Find "timeout" errors in filebeat-production-*

4. Start asking questions

Show me errors in production-* from the last hour
What are the top 10 services by log volume today in production-*?
Find logs containing "connection refused" in staging-*
Show error trends over the past 24 hours in filebeat-*
What fields are available in the logs-nginx-* index?

Tip: If you're not sure which index to use, just ask Claude — it will use the list_data_views tool to find the right one.

Tools

The server exposes 7 read-only tools:

search_logs

Search logs with filters, time ranges, and free-text queries.

Parameter Type Default Description
index string * Index pattern (e.g., logs-*, filebeat-*)
query string Free-text query (Lucene syntax)
service string Filter by kubernetes.container.name
from string Start time (now-1h, 2024-01-01T00:00:00Z)
to string End time (now)
filters object Key-value field filters (e.g., {"stream": "stderr"})
messageLevel string Log level inside JSON message (error, warn, info)
messageQuery string Phrase search within message field
excludeHealthChecks boolean false Exclude health/readiness probe logs
size number 50 Max results to return
sort asc/desc desc Sort order by timestamp

aggregate_logs

Run aggregations for analytics and trend analysis.

Parameter Type Default Description
index string * Index pattern
aggType enum terms, date_histogram, stats, or count
field string Field to aggregate on
service string Filter by service name
from / to string Time range
interval string 1h Interval for date_histogram
query string Free-text filter
messageQuery string Phrase search in message
filters object Key-value field filters

list_indices

List available data views filtered by pattern.

Parameter Type Default Description
pattern string * Glob-style filter (e.g., logs-*)

list_data_views

List all Kibana data views (index patterns). No parameters.

get_mapping

Get field names, types, and whether they are aggregatable for an index.

Parameter Type Description
index string Index pattern (e.g., filebeat-*)

get_document

Fetch a single document by its Elasticsearch ID.

Parameter Type Description
index string Index name or pattern
id string Document ID

cluster_health

Check Kibana connectivity and list sample data views. No parameters.

Configuration

All configuration is via environment variables in the env block of your MCP config.

Variable Required Default Description
ELASTIC_NODES Yes Kibana base URL (e.g., https://kibana.example.com)
ELASTIC_USERNAME No Basic auth username
ELASTIC_PASSWORD No Basic auth password
CF_ACCESS_TOKEN No auto Cloudflare Access JWT (see below)
KIBANA_SPACE No default Kibana space name
ELASTIC_TLS_REJECT_UNAUTHORIZED No true Set false for self-signed certificates
ELASTIC_REQUEST_TIMEOUT No 60000 Request timeout in milliseconds
ELASTIC_MAX_RESULTS No 500 Maximum number of search results
ALLOWED_SERVICES No (all) Comma-separated allowlist of kubernetes.container.name values

Index Patterns

The index parameter in search and aggregation tools accepts Elasticsearch index patterns. These depend on your setup. Common examples:

Setup Typical Pattern Example
Filebeat filebeat-* filebeat-2024.01.*
Logstash logstash-* logstash-production-*
Fluentd/Fluent Bit fluentd-* or fluent-bit-* fluent-bit-staging-*
Data streams logs-* logs-nginx-*
Custom per-env production-*, staging-* production-api-gateway*

Use the list_data_views tool to see what's available in your Kibana, or ask Claude: "What indices do we have?"

Service Allowlist

Restrict which Kubernetes services can be queried by setting ALLOWED_SERVICES:

"ALLOWED_SERVICES": "api-gateway,auth-service,payment-service"

When empty or unset, all services are accessible.

Authentication

Basic Auth

Set ELASTIC_USERNAME and ELASTIC_PASSWORD in the env block. These are sent as a standard HTTP Basic auth header on every request.

Cloudflare Zero Trust (optional)

If your Kibana is behind Cloudflare Zero Trust (formerly Cloudflare Access), the server handles token management automatically. No extra configuration is needed beyond the initial login.

How it works

When the server starts, it looks for a Cloudflare Access JWT to include as a cf-access-token header on every request to Kibana. The token resolution order is:

  1. Read from ~/.cloudflared/ cachecloudflared stores tokens as files named <hostname>-<audience>-token after a successful login
  2. Auto-refresh via cloudflared access login — if the cached token is expired or missing, the server runs cloudflared access login <url> which opens a browser for authentication (Node.js only, not in Docker)
  3. Fall back to CF_ACCESS_TOKEN env var — if the above steps fail, the server uses the token from the environment variable
  4. Retry on 401/403 — if a request fails with an auth error, the server re-reads the token from disk and retries once (handles cases where the token was refreshed externally)

Prerequisites

Install cloudflared:

# macOS
brew install cloudflared

# Linux (Debian/Ubuntu)
curl -fsSL https://pkg.cloudflare.com/cloudflare-main.gpg | sudo tee /usr/share/keyrings/cloudflare-main.gpg >/dev/null
echo "deb [signed-by=/usr/share/keyrings/cloudflare-main.gpg] https://pkg.cloudflare.com/cloudflare-main $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/cloudflare-main.list
sudo apt update && sudo apt install cloudflared

First-time setup

cloudflared access login https://your-kibana-url.com

A browser window opens for authentication. After completing the login, a JWT is cached in ~/.cloudflared/. The server reads this automatically — no need to copy tokens manually.

Token lifecycle

Scenario What happens
Token valid Used automatically from ~/.cloudflared/
Token expired Server runs cloudflared access login → browser opens → new token cached
Token expired (Docker) Browser can't open — re-run cloudflared access login on your host machine
Manual token Set CF_ACCESS_TOKEN env var to skip auto-detection entirely
Request gets 401/403 Server re-reads token from disk and retries once

Docker considerations

Docker containers can't open a browser for interactive Cloudflare login. Two options:

Option 1: Mount the host's token cache (recommended)

"-v", "/home/john/.cloudflared:/root/.cloudflared:ro"

The container reads your host's cached tokens. When they expire, re-run cloudflared access login on your host machine — the container sees the updated token immediately via the mounted volume.

Option 2: Pass token via environment variable

"-e", "CF_ACCESS_TOKEN=eyJhbGciOi..."

Obtain a token manually (cloudflared access login, then read the file from ~/.cloudflared/) and pass it directly. Note: this token will eventually expire and you'll need to update it.

Not using Cloudflare?

If your Kibana is not behind Cloudflare Zero Trust, you can ignore all of the above. The server will skip Cloudflare authentication entirely when no token is found and cloudflared is not installed.

Project Structure

src/
  main.ts                    # Entry point — registers tools and starts stdio transport
  kibana-client.ts           # Kibana HTTP client with auth and retry logic
  cf-token.ts                # Cloudflare Access token auto-management
  allowed-services.ts        # Service allowlist filtering
  utils/
    format-response.ts       # Response truncation and formatting
  tools/
    search-logs.tool.ts      # search_logs
    aggregate-logs.tool.ts   # aggregate_logs
    list-indices.tool.ts     # list_indices
    list-data-views.tool.ts  # list_data_views
    get-mapping.tool.ts      # get_mapping
    get-document.tool.ts     # get_document
    cluster-health.tool.ts   # cluster_health

License

MIT

Recommended Servers

playwright-mcp

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.

Official
Featured
TypeScript
Magic Component Platform (MCP)

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.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

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.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

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.

Official
Featured
TypeScript
Kagi MCP Server

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.

Official
Featured
Python
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Exa Search

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.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured