Skip to main content
konstantyn_diachenko
Community Advisor
Community Advisor
October 6, 2026

AI-Assisted AEM CDN Log Analysis with Elasticsearch MCP

  • October 6, 2026
  • 0 replies
  • 16 views

[OVERVIEW]
Adobe's open-source AEMCS CDN Log Analysis Tooling ships an ELK stack and four prebuilt Kibana dashboards for analyzing AEM as a Cloud Service CDN logs. The dashboards answer the questions they were designed for - cache hit ratio, traffic, WAF. Everything else means hand-writing Elasticsearch Query DSL or building a new visualization, which is slow even if you know the syntax and a hard stop if you don't.

I added an optional Elasticsearch MCP server to that stack, so you can point Claude Code, OpenAI Codex or GitHub Copilot at your indexed logs and just ask: "which client IPs came closest to the X requests/second rate limit, and when were the peaks?" The agent writes the query, runs it, and shows you the query it used so you can check it.

It runs as one more container behind a Docker Compose profile, so docker compose up -d behaves exactly as before and nobody who doesn't want it is affected. Enable it with docker compose --profile mcp up -d. The endpoint binds to localhost only, and access is read-only; a second deployment mode connects to a remote Elasticsearch using a scoped, read-only API key.

[IMPACT]
Time

- Deep ad-hoc investigations that used to take 6-8 hours (download logs, ingest, work out which fields matter, iterate on Query DSL, cross-check the numbers) now take about 15 minutes.
- Quick questions (top client IPs, error counts by URL, cache ratio for a given window) went from "build a visualization first" to about 30 seconds.

Quality and access

- Analysis is no longer gated on knowing Elasticsearch Query DSL. Anyone who can describe what they want to know can get an answer.
- The agent shows the query it ran, so results are reviewable rather than taken on faith: which matters when the output feeds a rate-limit or security decision.
- One-off questions stop generating throwaway Kibana dashboards.

[LESSONS]
Tips from actually using it

- Set the ground rules once, at the start of the session. Tell the agent: the index is aem-cdn-logs, the time field is timestamp and it's UTC, string fields need their .keyword subfield for aggregations, and use the search tool with Query DSL. Skip this and it guesses: usually aggregating on a text field, which quietly returns nothing. This one paragraph is the difference between the tool working and appearing broken.

- Ask to see the query before it runs. "Explain the Query DSL you intend to use before executing it." It takes five seconds and catches the expensive mistakes: wrong time range, wrong field, an aggregation that measures something other than what you asked.

- Watch the time range above everything else. Agents reach for now-24h by default, but CDN logs downloaded from Cloud Manager are historical, so you get zero hits and a confident explanation of nothing. Give it an absolute UTC range.

- Drill down in follow-ups instead of asking one enormous question. Start with "top 20 client IPs," then "what is that IP requesting," then "what user agent and status codes." The back-and-forth is where this genuinely beats a dashboard; you don't have to know the shape of the answer before you start.

- Treat approximate results as approximate. Elasticsearch terms aggregations and percentiles are both approximations. Ask what the denominator was: "median requests per second" computed only across seconds that had traffic is a very different number from one computed across the whole window, and the agent won't volunteer which it did.

- Cross-check one number in Kibana before acting on the whole analysis. Cheapest possible validation, and it catches the case where the query was valid but measured the wrong thing.

- Know when a dashboard is still the better tool. For recurring, known questions (cache hit ratio, WAF activity) the prebuilt dashboards win. MCP is for the one-off investigations where you don't yet know what you're looking for.

I'm preparing a series of articles to share this experience in more depth: the setup, and how I use it day to day.

[TRYABLE]
I raised a PR to the Adobe's tool: https://github.com/adobe/AEMCS-CDN-Log-Analysis-Tooling/pull/26

1. Start with the existing AEMCS CDN Log Analysis Tooling ELK workflow.

   Download CDN logs from Cloud Manager, unzip them if needed, and place them under an environment folder such as:

   ```bash
   ELK/logs/prod
   ```

   Then start the ELK stack:

   ```bash
   cd ELK
   docker compose up -d
   ```

2. Enable the optional MCP server.

   The MCP service is off by default, so the normal ELK workflow is unchanged. To enable AI-assisted querying, start Docker Compose with the `mcp` profile:

   ```bash
   cd ELK
   docker compose --profile mcp up -d
   ```

   This exposes the MCP endpoint locally at:

   ```text
   http://localhost:8080/mcp
   ```

3. Connect an AI coding agent.

   Configure Claude Code, OpenAI Codex, or GitHub Copilot in VS Code to use the local MCP endpoint:
   Claude Code (project .mcp.json config):
   ```json
   {
     "mcpServers": {
       "aem-cdn-logs-elk": {
         "type": "http",
         "url": "http://localhost:8080/mcp"
       }
     }
   }
   ```

4. Give the agent the ground rules before asking questions.

   Use a starter prompt like this:

   ```text
   You are helping analyze AEM as a Cloud Service CDN logs in Elasticsearch.
   Use the Elasticsearch MCP tools only for read-only analysis.
   The index is `aem-cdn-logs`.
   The time field is `timestamp` and timestamps are UTC.
   For aggregations on string fields, use the `.keyword` subfield.
   Before executing a query, explain the Query DSL you intend to run.
   After executing it, summarize the result and show the query used.
   Use absolute UTC time ranges. Do not assume `now-24h` unless I ask for it.
   ```

5. Ask focused investigation questions.

   Examples:

   ```text
   For 2026-09-10 00:00:00 UTC to 2026-09-10 23:59:59 UTC, show the top 20 client IPs by request count.
   ```
   ```text
   Which client IPs came closest to the 100 requests/second rate limit, and at what timestamps did they peak?
   ```
   ```text
   For this hostname and time window, calculate HIT, MISS, and PASS counts and the cache hit ratio.
   ```
   ```text
   Show the top URLs returning 5xx errors, grouped by status code and hostname.
   ```

6. Iterate in follow-up prompts.

   The workflow works best as a conversation:
   - Start broad: "top client IPs"
   - Drill into one result: "what paths did this IP request?"
   - Add context: "group by user agent and status code"
   - Validate: "show the exact query and denominator used"

7. Cross-check before acting.

   Before using the result for a rate-limit, caching, or security decision, validate at least one key number in Kibana. The value of the recipe is speed, but the agent's query should still be reviewed like any other operational analysis.

[SETUP]
To use this recipe, you need:

- Access to AEM as a Cloud Service CDN logs from Cloud Manager.
- The AEMCS CDN Log Analysis Tooling repository.
- Docker and Docker Compose installed locally.
- At least 4 GB of memory available for Docker.
- An MCP-capable AI client, such as Claude Code, OpenAI Codex, or GitHub Copilot in VS Code.
- The optional ELK MCP service running locally at:

  ```text
  http://localhost:8080/mcp
  ```

Start the MCP-enabled ELK stack with:

```bash
cd ELK
docker compose --profile mcp up -d
```

Minimal shareable MCP client configuration:

```json
{
  "mcpServers": {
    "aem-cdn-logs-elk": {
      "type": "http",
      "url": "http://localhost:8080/mcp"
    }
  }
}
```

For the default local ELK setup, no Elasticsearch credentials are required.

For a remote Elasticsearch setup, you also need:

- Network access to the Elasticsearch cluster.
- A scoped, read-only Elasticsearch API key.
- An `.env` file based on `ELK/mcp/.env.example`.

[SAMPLE_OUTPUT]
PR with the full implementation and documentation:

https://github.com/adobe/AEMCS-CDN-Log-Analysis-Tooling/pull/26

Copyable MCP client config:

```json
{
  "mcpServers": {
    "aem-cdn-logs-elk": {
      "type": "http",
      "url": "http://localhost:8080/mcp"
    }
  }
}
```

Optional local startup command:

```bash
cd ELK
docker compose --profile mcp up -d
```

MCP endpoint:

```text
http://localhost:8080/mcp
```