TL;DR: Your MCP server is reaching Elasticsearch but not logging in. Elasticsearch 8 has security on by default and answers every unauthenticated request with 401. Create an API key in Kibana and give it to the MCP server as `ES_API_KEY`.

```text
{"error":{"root_cause":[{"type":"security_exception","reason":"missing authentication credentials for REST request [/]"}]},"status":401}
```

## Fix it

1. In Kibana, go to Stack Management, Security, API Keys. Create a key. Important: the walkthrough notes that read-only does not include permission to list all indices, so grant the privileges the server needs (superuser works; scope it down if you can).

2. Copy the **encoded** key value (the long base64 string), not the raw `api_key` field.

3. Set it in the MCP server config. For elastic/mcp-server-elasticsearch:

```json
{
  "env": {
    "ES_URL": "your-cluster",
    "ES_API_KEY": "your-encoded-api-key"
  }
}
```

   Alternatively use `ES_USERNAME` and `ES_PASSWORD` with the `elastic` superuser.

4. Restart the MCP client.

   Expected: tools like list indices and search return data instead of 401.

## When to use this

- Every Elasticsearch tool call fails with 401 `missing authentication credentials`.
- `curl` without auth to the cluster returns the same 401 body (proves the cluster is up and security is on).

## When NOT to use this

- The error is `unable to authenticate` with credentials set. The key is wrong, expired, or invalidated. Create a new one.
- The error is 403. Auth worked; the key lacks privileges. Broaden the role descriptors.
- Connection refused or timeout. The cluster is unreachable.

## Compatibility

- elastic/mcp-server-elasticsearch.
- Elasticsearch 8.x with security enabled (default), Elastic Cloud, self-hosted.

## Why it happens

Elasticsearch 8 enables security by default, unlike older versions that answered anonymously. The MCP server has no credentials unless you configure them, so the first thing it hits is the 401. The error is verbose but the meaning is simple: nobody logged in.

## Edge cases

- Use the `encoded` value from the API key creation response. The raw `api_key` plus `id` pair also works but the encoded form is one string.
- Invalidated or expired keys fail with `unable to authenticate`, not `missing authentication credentials`. Different message, different fix: make a new key.
- Give each integration its own API key with an expiration, so rotation does not break everything at once.