Elasticsearch MCP Server

Search, inspect and manage Elasticsearch or OpenSearch clusters from an MCP client

By Se7en (individual) Python Local · stdio DatabasesDevOps and monitoring

61 popularity score ★ 316 ↓ 10k/mo

Connect your client

Local (PyPI)

Add in one click

Opens the app, which asks before it adds the server. Then replace each <NAME> in its settings with your value.

Or add it by command or config

It needs ELASTICSEARCH_HOSTS, ELASTICSEARCH_USERNAME, ELASTICSEARCH_PASSWORD. Replace each <NAME> with your value.

Claude CodeTerminal
claude mcp add elasticsearch -e ELASTICSEARCH_HOSTS=<ELASTICSEARCH_HOSTS> -e ELASTICSEARCH_USERNAME=<ELASTICSEARCH_USERNAME> -e ELASTICSEARCH_PASSWORD=<ELASTICSEARCH_PASSWORD> -- uvx elasticsearch-mcp-server
Claude Desktopclaude_desktop_config.json
{
  "mcpServers": {
    "elasticsearch": {
      "command": "uvx",
      "args": [
        "elasticsearch-mcp-server"
      ],
      "env": {
        "ELASTICSEARCH_HOSTS": "<ELASTICSEARCH_HOSTS>",
        "ELASTICSEARCH_USERNAME": "<ELASTICSEARCH_USERNAME>",
        "ELASTICSEARCH_PASSWORD": "<ELASTICSEARCH_PASSWORD>"
      }
    }
  }
}
Cursor~/.cursor/mcp.json
{
  "mcpServers": {
    "elasticsearch": {
      "command": "uvx",
      "args": [
        "elasticsearch-mcp-server"
      ],
      "env": {
        "ELASTICSEARCH_HOSTS": "<ELASTICSEARCH_HOSTS>",
        "ELASTICSEARCH_USERNAME": "<ELASTICSEARCH_USERNAME>",
        "ELASTICSEARCH_PASSWORD": "<ELASTICSEARCH_PASSWORD>"
      }
    }
  }
}
VS Code.vscode/mcp.json
{
  "servers": {
    "elasticsearch": {
      "type": "stdio",
      "command": "uvx",
      "args": [
        "elasticsearch-mcp-server"
      ],
      "env": {
        "ELASTICSEARCH_HOSTS": "<ELASTICSEARCH_HOSTS>",
        "ELASTICSEARCH_USERNAME": "<ELASTICSEARCH_USERNAME>",
        "ELASTICSEARCH_PASSWORD": "<ELASTICSEARCH_PASSWORD>"
      }
    }
  }
}
Codex~/.codex/config.toml
[mcp_servers.elasticsearch]
command = "uvx"
args = ["elasticsearch-mcp-server"]

[mcp_servers.elasticsearch.env]
ELASTICSEARCH_HOSTS = "<ELASTICSEARCH_HOSTS>"
ELASTICSEARCH_USERNAME = "<ELASTICSEARCH_USERNAME>"
ELASTICSEARCH_PASSWORD = "<ELASTICSEARCH_PASSWORD>"
Gemini CLITerminal
gemini mcp add --scope user -e ELASTICSEARCH_HOSTS=<ELASTICSEARCH_HOSTS> -e ELASTICSEARCH_USERNAME=<ELASTICSEARCH_USERNAME> -e ELASTICSEARCH_PASSWORD=<ELASTICSEARCH_PASSWORD> elasticsearch uvx -- elasticsearch-mcp-server
Local (from source)

Add in one click

Opens the app, which asks before it adds the server. Then replace each <NAME> in its settings with your value.

Or add it by command or config

It needs ELASTICSEARCH_HOSTS, ELASTICSEARCH_USERNAME, ELASTICSEARCH_PASSWORD. Replace each <NAME> with your value.

FirstTerminal
git clone https://github.com/cr7258/elasticsearch-mcp-server.git
Claude CodeTerminal
claude mcp add elasticsearch -e ELASTICSEARCH_HOSTS=<ELASTICSEARCH_HOSTS> -e ELASTICSEARCH_USERNAME=<ELASTICSEARCH_USERNAME> -e ELASTICSEARCH_PASSWORD=<ELASTICSEARCH_PASSWORD> -- uv --directory '<ABSOLUTE_PATH_TO_CLONE>' run elasticsearch-mcp-server
Claude Desktopclaude_desktop_config.json
{
  "mcpServers": {
    "elasticsearch": {
      "command": "uv",
      "args": [
        "--directory",
        "<ABSOLUTE_PATH_TO_CLONE>",
        "run",
        "elasticsearch-mcp-server"
      ],
      "env": {
        "ELASTICSEARCH_HOSTS": "<ELASTICSEARCH_HOSTS>",
        "ELASTICSEARCH_USERNAME": "<ELASTICSEARCH_USERNAME>",
        "ELASTICSEARCH_PASSWORD": "<ELASTICSEARCH_PASSWORD>"
      }
    }
  }
}
Cursor~/.cursor/mcp.json
{
  "mcpServers": {
    "elasticsearch": {
      "command": "uv",
      "args": [
        "--directory",
        "<ABSOLUTE_PATH_TO_CLONE>",
        "run",
        "elasticsearch-mcp-server"
      ],
      "env": {
        "ELASTICSEARCH_HOSTS": "<ELASTICSEARCH_HOSTS>",
        "ELASTICSEARCH_USERNAME": "<ELASTICSEARCH_USERNAME>",
        "ELASTICSEARCH_PASSWORD": "<ELASTICSEARCH_PASSWORD>"
      }
    }
  }
}
VS Code.vscode/mcp.json
{
  "servers": {
    "elasticsearch": {
      "type": "stdio",
      "command": "uv",
      "args": [
        "--directory",
        "<ABSOLUTE_PATH_TO_CLONE>",
        "run",
        "elasticsearch-mcp-server"
      ],
      "env": {
        "ELASTICSEARCH_HOSTS": "<ELASTICSEARCH_HOSTS>",
        "ELASTICSEARCH_USERNAME": "<ELASTICSEARCH_USERNAME>",
        "ELASTICSEARCH_PASSWORD": "<ELASTICSEARCH_PASSWORD>"
      }
    }
  }
}
Codex~/.codex/config.toml
[mcp_servers.elasticsearch]
command = "uv"
args = ["--directory", "<ABSOLUTE_PATH_TO_CLONE>", "run", "elasticsearch-mcp-server"]

[mcp_servers.elasticsearch.env]
ELASTICSEARCH_HOSTS = "<ELASTICSEARCH_HOSTS>"
ELASTICSEARCH_USERNAME = "<ELASTICSEARCH_USERNAME>"
ELASTICSEARCH_PASSWORD = "<ELASTICSEARCH_PASSWORD>"
Gemini CLITerminal
gemini mcp add --scope user -e ELASTICSEARCH_HOSTS=<ELASTICSEARCH_HOSTS> -e ELASTICSEARCH_USERNAME=<ELASTICSEARCH_USERNAME> -e ELASTICSEARCH_PASSWORD=<ELASTICSEARCH_PASSWORD> elasticsearch uv -- --directory '<ABSOLUTE_PATH_TO_CLONE>' run elasticsearch-mcp-server

Settings 12

ELASTICSEARCH_HOSTS Required: Comma-separated cluster addresses. Default https://localhost:9200.
ELASTICSEARCH_API_KEY secret Optional: Elasticsearch or Elastic Cloud API key, in place of username and password.
OPENSEARCH_HOSTS Optional: Cluster addresses for the opensearch-mcp-server program, used with OPENSEARCH_USERNAME and OPENSEARCH_PASSWORD. Default https://localhost:9200. For opensearch-mcp-server.
ELASTICSEARCH_CLUSTERS_FILE Optional: Path to a JSON file of named clusters. ELASTICSEARCH_CLUSTERS takes the same JSON inline, and the file wins when both are set. For multiple clusters.
DEFAULT_CLUSTER Optional: Named cluster used when a tool call gives none, the first one when unset. For multiple clusters.
ELASTICSEARCH_PROXY Optional: Proxy for all cluster requests: an http, https, socks5 or socks5h URL. OPENSEARCH_PROXY does the same for OpenSearch, and a cluster's own proxy key overrides it.
VERIFY_CERTS Optional: Set to true to check TLS certificates. Default false.
DISABLE_HIGH_RISK_OPERATIONS Optional: Set to true to hide the write tools. Default false.
DISABLE_OPERATIONS Optional: Comma-separated tools to hide in place of the default list. Read only when DISABLE_HIGH_RISK_OPERATIONS=true.
MCP_API_KEY secret Optional: Bearer token the SSE or streamable HTTP endpoint asks for. For HTTP transports.
Set together: basic auth
ELASTICSEARCH_USERNAME Required: Basic-auth user, or set ELASTICSEARCH_API_KEY instead.
ELASTICSEARCH_PASSWORD secret Required: Basic-auth password for ELASTICSEARCH_USERNAME.

What it does

This server connects an MCP client to one or more Elasticsearch or OpenSearch clusters through 20 tools. The read side lists and inspects indices, data streams and aliases, runs searches, fetches documents by ID, reports cluster health and statistics, and shows how an analyzer tokenizes a piece of text. Other tools create and delete indices, documents, data streams and aliases. There is also general_api_request, which sends any HTTP request to the cluster's REST API. In practice that means it can do whatever the cluster credentials allow.

The PyPI package installs two programs: elasticsearch-mcp-server (Elasticsearch 8.x client) and opensearch-mcp-server (OpenSearch 1.x to 3.x). For Elasticsearch 7.x or 9.x you install elasticsearch-mcp-server-es7 or elasticsearch-mcp-server-es9 instead. It speaks stdio by default. With --transport sse or streamable-http it listens on 127.0.0.1:8000 unless you pass --host or --port. You can define several named clusters, and then every tool takes an optional cluster argument. Set RESPONSE_FORMAT=gcf if you want results handed to the model in a compact format rather than JSON.

Traffic can go through an HTTP, HTTPS or SOCKS5 proxy via ELASTICSEARCH_PROXY or OPENSEARCH_PROXY, or a proxy key per cluster. SOCKS support ships with the package (pyproject.toml), so nothing extra needs installing. The code pins that proxy over any HTTP_PROXY, HTTPS_PROXY or NO_PROXY in the environment (src/clients/proxy.py).

Two more things the README does not spell out. DISABLE_OPERATIONS is only read when DISABLE_HIGH_RISK_OPERATIONS=true, and its list replaces the default set of write tools. A write tool you leave off it stays available (src/risk_config.py). In HTTP mode the server also answers /healthz and /readyz for Kubernetes probes, and /readyz returns 503 if the cluster ping fails or takes longer than 5 seconds (src/server.py).

What it needs

RuntimePython 3.10+
Runs onmacOS, Windows, Linux
Elasticsearch or OpenSearchYour own instanceA reachable cluster plus a username and password or an Elasticsearch API key. Elastic Cloud API keys work too
Also
  • uv, for the uvx command

Pick the package that matches the cluster: elasticsearch-mcp-server for Elasticsearch 8.x, elasticsearch-mcp-server-es7 or elasticsearch-mcp-server-es9 for 7.x or 9.x, or the opensearch-mcp-server program from this package for OpenSearch 1.x to 3.x.

Limits

  • Not covered Built against one Elasticsearch client major version (elasticsearch 8.17.2 here), so 7.x and 9.x clusters need the -es7 or -es9 package
  • Not covered API-key sign-in is for Elasticsearch only. OpenSearch takes a username and password
  • Limit TLS certificates are not checked unless VERIFY_CERTS=true
  • Limit REQUEST_TIMEOUT has no default of its own, so the client library's timeout applies when it is unset
  • Limit In HTTP mode MCP_API_KEY is optional, and without it the endpoint accepts anyone who can reach it
  • Limit A proxy URL with another scheme or no host stops the server at start with an error

Each package is built against one Elasticsearch client major version (this one pins elasticsearch 8.17.2), so 7.x and 9.x clusters need the separate -es7 or -es9 package. API-key sign-in works for Elasticsearch only; OpenSearch takes a username and password. TLS certificates are not checked unless VERIFY_CERTS=true. REQUEST_TIMEOUT has no default of its own, so the client library's timeout applies. In HTTP mode, MCP_API_KEY is not required, and without it the endpoint accepts anyone who can reach it.

Who it suits

Suits developers and operators who run their own Elasticsearch or OpenSearch clusters and want to query, inspect or tidy indices from a chat client, including across several named clusters. Because general_api_request and the delete tools can change or remove data, set DISABLE_HIGH_RISK_OPERATIONS=true and use a read-only API key when pointing it at production. It is a community project, not from Elastic. Elastic publishes its own server, elastic/mcp-server-elasticsearch, which we also list; choose that one if you want a vendor-maintained server.

Tools 20

10 only read, 4 change things, 6 can delete or overwrite. A ? marks an optional parameter.

general_api_request deletes
Send any HTTP request to the cluster's REST APImethod: stringpath: stringparams?: objectbody?: objectcluster?: string
list_indices
List the cluster's indicescluster?: string
get_index
Show mappings, settings and aliases of one or more indicesindex: stringcluster?: string
create_index changes
Create an indexindex: stringbody?: objectcluster?: string
delete_index deletes
Remove an indexindex: stringcluster?: string
create_data_stream changes
Create a data stream from an existing index templatename: stringcluster?: string
get_data_stream
Show details of one or more data streamsname?: stringcluster?: string
delete_data_stream deletes
Remove data streams together with their backing indicesname: stringcluster?: string
search_documents
Run a search query against an indexindex: stringbody: objectcluster?: string
index_document deletes
Add a document to an index or replace oneindex: stringdocument: objectid?: stringcluster?: string
get_document
Fetch one document by its IDindex: stringid: stringcluster?: string
delete_document deletes
Remove one document by its IDindex: stringid: stringcluster?: string
delete_by_query deletes
Remove every document that matches a queryindex: stringbody: objectcluster?: string
get_cluster_health
Report the cluster's health statuscluster?: string
get_cluster_stats
Give summary statistics for the clustercluster?: string
list_aliases
List all aliasescluster?: string
get_alias
Show the aliases of an indexindex: stringcluster?: string
put_alias changes
Add or change an alias on an indexindex: stringname: stringbody: objectcluster?: string
delete_alias changes
Remove an alias from an indexindex: stringname: stringcluster?: string
analyze_text
Show how an analyzer or custom chain splits text into tokenstext: stringindex?: stringanalyzer?: stringtokenizer?: stringfilter?: arraychar_filter?: arrayexplain?: booleanattributes?: arraycluster?: string

Similar servers