elastic-mcp
elastic-mcp is a Model Context Protocol (MCP) server for Elasticsearch, offering read-only access by default with optional write operations.
Search & Data Retrieval
search— Execute full Query DSL searches with queries, aggregations, sorting, pagination, and source filteringcount— Count documents matching an optional queryget_document— Fetch a single document by index and IDesql— Run ES|QL queries with column metadata and keyed row objects (requires Elasticsearch 8.11+)
Index Inspection
list_indices— List indices with health, status, doc count, and size (falls back to names-only ifmonitorprivilege is missing)get_mapping— Retrieve field mappings (falls back to_field_capsifview_index_metadatais missing)get_settings— Get settings for one or more indicesget_aliases— List index aliases, optionally filtered by namelist_shards— List shards with role, state, doc count, store size, and node info
Cluster Monitoring
cluster_health— Get cluster health, optionally scoped to specific indicescluster_stats— Get cluster-wide statistics (indices, nodes, shards, resource usage)cluster_info— Get basic cluster info (name, UUID, version)list_nodes— List nodes with role, heap, CPU, and load info
Kibana Integration
get_kibana_object— Fetch a Kibana saved object (dashboard, visualization, lens, index-pattern, etc.) by<type>:<id>, with inline JSON decoding and reference resolution
Optional Write Operations (enabled via ELASTICSEARCH_ENABLE_WRITES=true)
Index, update, or delete documents
Create or delete indices
Notable Characteristics
Read-only by default, making it safe out of the box
Supports Elasticsearch 8.x and 9.x with automatic version detection (or manual pinning)
Works with deployments behind a reverse proxy with a base path
Degrades gracefully when certain privileges (e.g.,
monitor,view_index_metadata) are missingSupports API key and basic auth, with optional CA fingerprint and TLS verification control
Provides read-only tools for searching, counting, retrieving documents, listing indices, getting mappings, settings, aliases, shard info, cluster health, stats, node info, and Kibana saved objects; optional write tools for indexing, updating, deleting documents, and managing indices. Supports Elasticsearch 8.x and 9.x, base paths, and API key authentication.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@elastic-mcp search the orders index for pending shipments"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
elastic-mcp
⚠️ Disclaimer: this MCP server was vibe coded. It was built iteratively with an AI assistant and is typechecked and unit-tested, but review it yourself before relying on it — especially the write tools — and use it at your own risk.
A Model Context Protocol server for Elasticsearch, written in JavaScript with JSDoc types checked by TypeScript (@ts-check / checkJs). Read-only by default, with optional write tools.
It exposes search, index inspection, and cluster information tools over the stdio transport, and transparently supports:
Elasticsearch deployments served behind a reverse proxy under a base path (for example
https://host/elasticsearch) — something the official client does not handle out of the box.Both Elasticsearch 8.x and 9.x clusters — the v9 client speaks
compatible-with=9and is rejected by 8.x clusters, so the matching client major is selected at startup (auto-detected or pinned).
Tested in corporate environments where API keys are often issued to restricted users with limited privileges (e.g. index
readonly, without clustermonitororview_index_metadata). The server is built to degrade gracefully in these setups rather than fail outright — it falls back to lower-privilege APIs where possible and surfaces clear authorization errors otherwise. See Elasticsearch version compatibility and the privilege fallback table for details.
Usage
Run it straight from npm with npx (no install needed — set the environment variables from
Configuration first):
ELASTICSEARCH_URL=http://localhost:9200/elastic npx elastic-mcpOr install it globally to get the elastic-mcp command on your PATH:
npm install -g elastic-mcp
ELASTICSEARCH_URL=http://localhost:9200/elastic elastic-mcpClaude Desktop / Claude Code
Add the server to your MCP client configuration:
{
"mcpServers": {
"elastic": {
"command": "npx",
"args": ["-y", "elastic-mcp"],
"env": {
"ELASTICSEARCH_URL": "https://host/elasticsearch",
"ELASTICSEARCH_API_KEY": "<base64-api-key>"
}
}
}
}Related MCP server: Elasticsearch MCP Server
Tools
Read tools
Always registered, and all marked read-only (readOnlyHint).
Tool | Description |
| Run a Query DSL search (query, aggs, sort, size, from, _source). |
| Count documents matching an optional query. |
| Run an ES|QL query (complete query string); returns column metadata plus keyed row objects. Requires Elasticsearch 8.11+. |
| Fetch a single document by index and id. |
| List indices with health, status, doc count, and size; falls back to names-only via |
| Get field mappings for one or more indices; falls back to read-level |
| Get settings for one or more indices. |
| List index aliases. |
| List shards with role, state, doc count, store size, and node (equivalent to |
| Fetch a Kibana saved object by |
| Cluster health, optionally scoped to indices. |
| Cluster-wide statistics. |
| Cluster name, UUID, and version. |
| List nodes with role, heap, CPU, and load. |
Write tools
Off by default. Registered only when ELASTICSEARCH_ENABLE_WRITES=true. Each is marked
destructiveHint (except create_index) so MCP clients can prompt for confirmation, and of course only
works if the API key carries the matching write privileges.
Tool | Description |
| Create or replace a document (auto-generates an id if omitted; |
| Partially update a document by id, with optional upsert. |
| Delete a single document by id. |
| Create an index, optionally with mappings, settings, and aliases. |
| Permanently delete one or more indices — cannot be undone. |
Configuration
Configuration is read from environment variables (see .env.example):
Variable | Required | Description |
| yes | Endpoint URL, optionally including a base path. |
| no | Base64 API key; takes precedence over basic auth. |
| no | Basic-auth username. |
| no | Basic-auth password. |
| no | SHA-256 fingerprint of the CA certificate. |
| no | Defaults to |
| no |
|
| no | Set to |
Elasticsearch version compatibility
The official client always sends a compatible-with=<major> media type that matches its own major
version, and a cluster of a different major rejects it. To work against both 8.x and 9.x clusters, both
client majors are bundled and the right one is chosen at startup:
auto(default) — probe the cluster's root endpoint (with a plainapplication/jsonrequest that side-steps the compatibility header) and pick the matching client major. Anything up to 8.x uses the v8 client; 9.x and newer use the v9 client.8/9— pin the client major explicitly and skip the probe.
Note: the root probe requires the
cluster:monitor/mainprivilege. Index-scoped API keys often lack it (it can only be granted by an admin), in which case the probe fails withaction [cluster:monitor/main] is unauthorized. When that happens the server logs a warning and falls back to the v8 client, which speakscompatible-with=8— accepted by both 8.x and 9.x clusters — so search and index inspection keep working. SetELASTICSEARCH_API_VERSIONexplicitly to skip the probe (and the warning) entirely.
Base path support
When ELASTICSEARCH_URL contains a path (e.g. https://host/elasticsearch), the URL is split into its
origin (https://host) and prefix (/elasticsearch). A custom connection class prepends the prefix to every
request path, because the official client routes requests against the origin only and silently drops the path.
Creating an API key
By default the server is read-only, so it only needs cluster monitor rights (for cluster_health,
cluster_stats, cluster_info, list_nodes, and the _cat listings) plus read and
view_index_metadata on the indices you want to expose. Create a least-privilege key with the
Create API key API:
POST /_security/api_key
{
"name": "elastic-mcp",
"role_descriptors": {
"elastic_mcp_read_only": {
"cluster": ["monitor"],
"indices": [
{
"names": ["*"],
"privileges": ["read", "view_index_metadata"]
}
]
}
}
}Or with curl:
curl -u elastic -X POST "$ELASTICSEARCH_URL/_security/api_key" \
-H 'Content-Type: application/json' \
-d '{
"name": "elastic-mcp",
"role_descriptors": {
"elastic_mcp_read_only": {
"cluster": ["monitor"],
"indices": [
{ "names": ["*"], "privileges": ["read", "view_index_metadata"] }
]
}
}
}'The response contains an encoded field — that base64 value is exactly what ELASTICSEARCH_API_KEY expects:
{
"id": "VuaCfGcBCdbkQm-e5aOx",
"name": "elastic-mcp",
"api_key": "ui2lp2axTNmsyakw9tvNnw",
"encoded": "VnVhQ2ZHY0JDZGJrUW0tZTVhT3g6dWkybHAyYXhUTm1zeWFrdzl0dk5udw=="
}ELASTICSEARCH_API_KEY=VnVhQ2ZHY0JDZGJrUW0tZTVhT3g6dWkybHAyYXhUTm1zeWFrdzl0dk5udw==Restrict indices[].names to specific index names or patterns to narrow access further.
Kibana saved-object access (only for get_kibana_object)
get_kibana_object reads Kibana's saved objects straight from the .kibana_analytics and .kibana
indices. These are restricted system indices, so a plain read on * does not reach them — the role
needs a dedicated entry that opts in with allow_restricted_indices. Add it alongside the existing read
entry (keep the wildcard entry at false so the key cannot read other system indices such as .security-*):
{
"name": "elastic-mcp",
"role_descriptors": {
"elastic_mcp_read_only": {
"cluster": ["monitor"],
"indices": [
{ "names": ["*"], "privileges": ["read", "view_index_metadata"], "allow_restricted_indices": false },
{ "names": [".kibana*"], "privileges": ["read"], "allow_restricted_indices": true }
]
}
}
}To widen an existing key without rotating it, the Update API key API
(PUT /_security/api_key/<id>) rewrites its role_descriptors in place — the id and encoded value are
unchanged, so ELASTICSEARCH_API_KEY does not need updating. Omit this entry entirely if you do not use
get_kibana_object; the tool then returns an authorization error and the rest of the server is unaffected.
Write privileges (only if ELASTICSEARCH_ENABLE_WRITES=true)
The read-only key above cannot mutate data — the write tools would return authorization errors. To allow
them, add the relevant index privileges: write (covers index_document, update_document,
delete_document), create_index, and delete_index:
{
"name": "elastic-mcp",
"role_descriptors": {
"elastic_mcp_read_write": {
"cluster": ["monitor"],
"indices": [
{
"names": ["*"],
"privileges": ["read", "view_index_metadata", "write", "create_index", "delete_index"]
}
]
}
}
}Grant only the subset you need — for example drop delete_index if you never delete indices. Cluster
monitor remains optional (see the fallback table below).
Graceful privilege degradation
Some tools degrade gracefully when privileges are missing, falling back once to a lower-privilege API and remembering that for the rest of the process so they don't retry the rejected endpoint:
Tool | Needs | Fallback when missing | Granted by |
| cluster |
|
|
|
|
|
|
So a key with only read + view_index_metadata (or even just read) still gets useful results from
search, count, esql, get_document, get_mapping, and list_indices. The tools that have no lower-privilege
equivalent — cluster_health, cluster_stats, cluster_info, list_nodes (cluster monitor),
get_settings, get_aliases (view_index_metadata), and get_kibana_object (restricted .kibana* read,
see above) — return an authorization error without the privilege.
Contributing
See CLAUDE.md for the project layout, architecture notes, and coding conventions.
License
ISC — see LICENSE.
Available Tools
14 toolscluster_healthCluster healthBRead-only
Get the health of the cluster, optionally scoped to specific indices.
Inputs: index, waitForStatus.
cluster_infoCluster infoARead-only
Get basic cluster information: name, UUID, and Elasticsearch version (the root endpoint).
Inputs: no named parameters.
cluster_statsCluster statsARead-only
Get cluster-wide statistics covering indices, nodes, shards, and resource usage.
Inputs: no named parameters.
countCount documentsARead-only
Count the documents in an index that match an optional Query DSL query.
Inputs: index (required), query.
esqlRun an ES|QL queryARead-only
Run an ES|QL (Elasticsearch Query Language) query and return the result as column metadata plus row objects. Good for filtering, STATS aggregations, and sorting expressed as a piped query string, e.g. FROM idx | WHERE status == "open" | STATS count = COUNT(*) BY host | SORT count DESC. Requires Elasticsearch 8.11+.
Inputs: query (required).
get_aliasesGet aliasesARead-only
List index aliases, optionally filtered by name (equivalent to _cat/aliases). Falls back to the index-level _resolve/index API when the cluster "monitor" privilege is missing.
Inputs: name.
get_documentGet document by idARead-only
Fetch a single document from an index by its id.
Inputs: id (required), index (required).
get_kibana_objectGet Kibana saved objectARead-only
Fetch a Kibana saved object (visualization, lens, dashboard, index-pattern, search, map, tag, ...) by ":" reference. Decodes the JSON-as-string fields Kibana stores inline (visState, searchSourceJSON, ...) and resolves references[] to the titles of the objects they point at. Reads .kibana_analytics and .kibana directly, so the API key needs read access to those indices.
Inputs: ref (required).
get_mappingGet index mappingARead-only
Get the field mappings for one or more indices. Falls back to the read-level _field_caps API (field names and types) when the index "view_index_metadata" privilege is missing.
Inputs: index (required).
get_settingsGet index settingsARead-only
Get the settings for one or more indices.
Inputs: index (required).
list_indicesList indicesARead-only
List indices with their health, status, document count, and size (equivalent to _cat/indices). Falls back to the index-level _resolve/index API (names only) when the cluster "monitor" privilege is missing.
Inputs: index.
list_nodesList nodesARead-only
List the nodes in the cluster with role, heap, CPU, and load information (equivalent to _cat/nodes).
Inputs: no named parameters.
list_shardsList shardsARead-only
List the cluster's shards with their primary/replica role, state, document count, store size, and hosting node (equivalent to _cat/shards). The docs and store columns come back null without the cluster "monitor" privilege; there is no lower-privilege source for per-shard rows, so a missing privilege surfaces as an error.
Inputs: index.
searchSearch documentsARead-only
Run an Elasticsearch search using Query DSL and return the matching hits and aggregations.
Inputs: index (required), aggs, from, size, +3 more.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 14 tools
The tool set maps cleanly to distinct Elasticsearch endpoints: cluster, nodes, shards, indices, documents, mappings, settings, aliases, and Kibana objects. Search, count, and esql overlap somewhat as query paths, but their descriptions clearly differentiate Query DSL hits/aggregations, simple counts, and ES|QL pipelines.
Naming is mostly predictable: list_* enumerates cluster resources, get_* fetches specific objects or metadata, cluster_* covers cluster-level views, and search/count/esql are self-explanatory actions. The mix of list_/get_ and bare verbs is a minor inconsistency, but it is still readable and not chaotic.
14 tools is well within the ideal range and each tool covers a major Elasticsearch operation area: cluster, nodes, shards, indices, documents, queries, and Kibana. No tool feels redundant or excessive for the apparent read/query/monitoring scope.
As a read/query/monitoring surface, it covers the main workflows: cluster health and stats, node/shards inspection, index metadata, aliases, mappings, documents, multiple query languages, and Kibana saved objects. The obvious gap is the absence of write/management tools such as create, update, or delete, so the server is complete only for read-oriented use.
Maintenance
Related MCP Connectors
A Model Context Protocol server for Wix AI tools
MCP server for searching Airweave collections with natural language queries.
A comprehensive Model Context Protocol (MCP) server that enables AI assistants to interact with yo…
Related MCP Servers
- AlicenseBqualityAmaintenanceFacilitates interaction with Elasticsearch clusters by allowing users to perform index operations, document searches, and cluster management via a Model Context Protocol server and natural language commands.20317Apache 2.0
- FlicenseNot gradedqualityDmaintenanceA Model Context Protocol server that enables LLMs to interact with Elasticsearch clusters, allowing them to manage indices and execute search queries using natural language.2-
- AlicenseAqualityDmaintenanceA comprehensive Model Context Protocol server that integrates Elasticsearch search with file operations, document validation, and version control to transform AI assistants into powerful knowledge management systems.27145 PyPI27MIT
- AlicenseBqualityDmaintenanceAn MCP server that enables interaction with Elasticsearch and OpenSearch clusters for searching documents and managing indices. It provides tools for cluster health monitoring, index configuration, and general API requests.16Apache 2.0