← MCP server and skill grades

mcp-server-elasticsearch

elastic/mcp-server-elasticsearch

C
Type
MCP server
Scanned
Oct 29, 2026
Version
9e64b842f222
Files read
37

This MCP server connects AI agents to an Elasticsearch cluster to list indices, inspect mappings and shards, and run Search DSL and ES|QL queries. The biggest risk is that running the server in HTTP mode exposes the /mcp and /mcp/sse endpoints without authentication while falling back to the server's configured Elasticsearch credentials, and binds to 0.0.0.0 by default in container mode.

What it can reach

Network
Connects to the configured Elasticsearch cluster over HTTP/HTTPS, and in HTTP mode listens for incoming connections on TCP port 8080 (or 8000 in Dockerfile-8000).
Secrets
Reads Elasticsearch credentials (ES_API_KEY, ES_USERNAME, ES_PASSWORD) and configuration settings from environment variables and .env files.
Files
Reads a local .env file if present and an optional JSON5 configuration file specified via the --config flag.

Findings

1 high1 medium2 low
  1. HighUnauthenticated HTTP server falls back to configured Elasticsearch credentials

    src/servers/elasticsearch/mod.rs:93

    When the server is run in HTTP mode, the /mcp and /mcp/sse endpoints do not require authentication. If an incoming HTTP request does not include an Authorization header, EsClientProvider::get returns the default client configured with the server's environment credentials (ES_API_KEY or ES_USERNAME/ES_PASSWORD). Any client able to reach the HTTP listener can query the Elasticsearch cluster using the server's credentials without authenticating.

    Fix: Require an Authorization header on all HTTP requests when running in HTTP mode, or do not fall back to server-side credentials for unauthenticated HTTP requests unless explicitly enabled.

  2. MediumHTTP server binds to all network interfaces in container mode

    src/lib.rs:66

    When CONTAINER_MODE is enabled (which is set by default in the provided Dockerfiles), the HTTP server binds to 0.0.0.0:8080 instead of 127.0.0.1:8080. If the container port is published on the host without interface restrictions (such as docker run -p 8080:8080 in the README), the unauthenticated MCP server is exposed to the surrounding network.

    Fix: Recommend binding published container ports to localhost (-p 127.0.0.1:8080:8080) in documentation, and require authentication before binding to non-loopback interfaces.

  3. LowUnpinned Git branch dependency for elasticsearch crate

    Cargo.toml:38

    The elasticsearch crate dependency points to a mutable Git branch (new-with-creds) rather than a pinned commit hash or a published version on crates.io. Building from source without --locked could fetch modified upstream code.

    Fix: Pin the Git dependency to a specific commit SHA using rev or use an official release version.

  4. LowUnhandled empty mapping response causes panic in get_mappings

    src/servers/elasticsearch/base_tools.rs:137

    In get_mappings, the code calls .unwrap() on the first item of the returned mapping map. If a wildcard index pattern matches no indices and Elasticsearch returns an empty JSON object, the handler will panic.

    Fix: Replace .unwrap() with proper handling for an empty map, returning a message that no mappings were found for the given index.