← mcp-for-kibana

MCP savings study

Claude Code on one Kibana job, 600 runs, three models: through the mcp-for-kibana MCP server, or through Kibana's REST API.

With MCP, Claude Code did the same Kibana job cheaper and faster than with Direct API, with each of the three models. Median cost per run fell 24% (Sonnet 5.5) to 69% (Haiku 5.5); median time per run fell 32% (Sonnet 5.5) to 65% (Haiku 5.5). All six 95% intervals lie wholly below 1.

These are warm-cache numbers: 593 of 600 runs (99%) started with the prompt already cached. On a cold cache, with one run each, MCP cost more for Sonnet 5.5 and Opus 5.5, and still saved for Haiku 5.5.

The two setups. MCP: Claude Code reaches Kibana through the tools of the mcp-for-kibana server (0.4.0). Direct API: Claude Code calls Kibana's REST API itself from the shell, with the pinned Kibana API reference. Everything else is the same.

Results describe Claude Code with each model, not the model alone. A ratio is the median on MCP ÷ the median on Direct API: below 1, MCP is cheaper or faster.

Savings per model

Haiku 5.5 saved the most on both measures. With 100 runs per model and setup, the intervals are narrow.

Cost per run, MCP ÷ Direct API

0 0.5 1 1.5 ← MCP lower MCP higher → Haiku 5.5 Haiku 5.5, cost: MCP ÷ Direct API = 0.31, 95% interval 0.29–0.32 0.31 (0.29–0.32) Sonnet 5.5 Sonnet 5.5, cost: MCP ÷ Direct API = 0.76, 95% interval 0.73–0.79 0.76 (0.73–0.79) Opus 5.5 Opus 5.5, cost: MCP ÷ Direct API = 0.56, 95% interval 0.55–0.59 0.56 (0.55–0.59)

Time per run, MCP ÷ Direct API

0 0.5 1 1.5 ← MCP lower MCP higher → Haiku 5.5 Haiku 5.5, time: MCP ÷ Direct API = 0.35, 95% interval 0.33–0.36 0.35 (0.33–0.36) Sonnet 5.5 Sonnet 5.5, time: MCP ÷ Direct API = 0.68, 95% interval 0.67–0.69 0.68 (0.67–0.69) Opus 5.5 Opus 5.5, time: MCP ÷ Direct API = 0.62, 95% interval 0.58–0.66 0.62 (0.58–0.66)
Medians with 95% percentile-bootstrap intervals (10,000 resamples). Shared scale; dashed line at 1 = same as Direct API. Data: study/data/analysis.json (ratios).

Per model and setup

On Direct API, Haiku 5.5 took the longest of all six combinations; on MCP it was the cheapest by far. All 600 of 600 counted runs passed every check.

SetupCost per runTime per runTool calls
Haiku 5.5
MCP$0.00670.0065–0.006836.6 s35.8–37.31616–16
Direct API$0.02190.0211–0.0226105.8 s101.6–110.22726–28.5
Sonnet 5.5
MCP$0.07740.0767–0.078332.4 s31.9–32.61515–15
Direct API$0.10160.0985–0.105547.5 s46.8–48.21111–12
Opus 5.5
MCP$0.17330.1709–0.175353.8 s52.3–56.31414–14
Direct API$0.30840.2925–0.314986.8 s83.2–92.71414–15
Median per run, 95% interval below it. Cost is list-price cost (Anthropic's published prices, not a bill), as each run came; caches were not controlled. Time runs from the CLI's start to its result. A tool call is one MCP tool call on MCP, or one shell command on Direct API (a command can bundle several Kibana requests). Data: study/data/analysis.json (per_model_arm).

Where the time goes exploratory

Not planned before the runs: it suggests where to look, not what holds. On MCP, the time saved is the model's time. A median run spent 25.9 s in model requests instead of 92.7 s with Haiku 5.5, 23.8 s instead of 37.3 s with Sonnet 5.5, and 45.0 s instead of 76.9 s with Opus 5.5. Tool time outside those requests stayed between 5.1 and 8.7 s.

0 s 30 s 60 s 90 s 120 s Haiku 5.5 MCP Haiku 5.5, MCP: model requests 25.9 s (95% interval 25.3–26.6) Haiku 5.5, MCP: tools outside requests 7.2 s (95% interval 6.8–7.6) Haiku 5.5, MCP: idle 3.4 s (95% interval 3.4–3.5) 36.6 s Direct API Haiku 5.5, Direct API: model requests 92.7 s (95% interval 89.4–97.2) Haiku 5.5, Direct API: tools outside requests 8.6 s (95% interval 8.3–8.8) Haiku 5.5, Direct API: idle 3.0 s (95% interval 3.0–3.1) 105.8 s Sonnet 5.5 MCP Sonnet 5.5, MCP: model requests 23.8 s (95% interval 23.3–24.4) Sonnet 5.5, MCP: tools outside requests 5.1 s (95% interval 5.0–5.4) Sonnet 5.5, MCP: idle 3.2 s (95% interval 3.2–3.3) 32.4 s Direct API Sonnet 5.5, Direct API: model requests 37.3 s (95% interval 36.4–38.1) Sonnet 5.5, Direct API: tools outside requests 8.7 s (95% interval 8.5–8.9) Sonnet 5.5, Direct API: idle 1.7 s (95% interval 1.7–1.8) 47.5 s Opus 5.5 MCP Opus 5.5, MCP: model requests 45.0 s (95% interval 43.1–46.5) Opus 5.5, MCP: tools outside requests 6.0 s (95% interval 5.6–6.4) Opus 5.5, MCP: idle 3.3 s (95% interval 3.2–3.3) 53.8 s Direct API Opus 5.5, Direct API: model requests 76.9 s (95% interval 72.8–82.6) Opus 5.5, Direct API: tools outside requests 8.2 s (95% interval 8.0–8.4) Opus 5.5, Direct API: idle 2.0 s (95% interval 1.9–2.1) 86.8 s
0 s 30 s 60 s 90 s 120 s Haiku 5.5 MCP Haiku 5.5, MCP: model requests 25.9 s (95% interval 25.3–26.6) Haiku 5.5, MCP: tools outside requests 7.2 s (95% interval 6.8–7.6) Haiku 5.5, MCP: idle 3.4 s (95% interval 3.4–3.5) 36.6 s Direct API Haiku 5.5, Direct API: model requests 92.7 s (95% interval 89.4–97.2) Haiku 5.5, Direct API: tools outside requests 8.6 s (95% interval 8.3–8.8) Haiku 5.5, Direct API: idle 3.0 s (95% interval 3.0–3.1) 105.8 s Sonnet 5.5 MCP Sonnet 5.5, MCP: model requests 23.8 s (95% interval 23.3–24.4) Sonnet 5.5, MCP: tools outside requests 5.1 s (95% interval 5.0–5.4) Sonnet 5.5, MCP: idle 3.2 s (95% interval 3.2–3.3) 32.4 s Direct API Sonnet 5.5, Direct API: model requests 37.3 s (95% interval 36.4–38.1) Sonnet 5.5, Direct API: tools outside requests 8.7 s (95% interval 8.5–8.9) Sonnet 5.5, Direct API: idle 1.7 s (95% interval 1.7–1.8) 47.5 s Opus 5.5 MCP Opus 5.5, MCP: model requests 45.0 s (95% interval 43.1–46.5) Opus 5.5, MCP: tools outside requests 6.0 s (95% interval 5.6–6.4) Opus 5.5, MCP: idle 3.3 s (95% interval 3.2–3.3) 53.8 s Direct API Opus 5.5, Direct API: model requests 76.9 s (95% interval 72.8–82.6) Opus 5.5, Direct API: tools outside requests 8.2 s (95% interval 8.0–8.4) Opus 5.5, Direct API: idle 2.0 s (95% interval 1.9–2.1) 86.8 s
Median seconds per run on the clock, without double counting (model requests + tool time outside them + idle = wall time); each part is its own median, so the parts need not add up exactly to the median wall time printed at the end. From 27,854 of 27,860 CLI spans (claude_code.llm_request, claude_code.tool.execution) attached to the counted runs. Data: study/data/exploratory.json (time_breakdown), from study/data/spans/spans.jsonl.

One MCP tool call takes 6 to 9 times as long as one shell command, yet tool time does not grow: the CLI starts a tool while the model's response is still streaming, so on MCP a median 2.1 to 4.6 s of tool time per run runs under the model's requests.

ModelMCP: one tool callDirect API: one shell command
Haiku 5.5508 ms449–574 · n = 1,58655 ms53–59 · n = 2,738
Sonnet 5.5589 ms543–631 · n = 1,49586 ms78–98 · n = 1,120
Opus 5.5480 ms416–534 · n = 1,40278 ms70–85 · n = 1,390
Median duration of one call, 95% interval and number of calls below it. The interval resamples calls as if independent, so it is narrower than a run-level one. Data: study/data/exploratory.json (time_breakdown.single_call_ms).

The time saving is not harness overhead: by the CLI's own duration the ratios are 0.32 (Haiku 5.5), 0.64 (Sonnet 5.5) and 0.60 (Opus 5.5), each interval wholly below 1 (time_ratio_cli in study/data/exploratory.json).

Cache: cold against warm exploratory

On MCP, the cached prompt carries the server's tool definitions: a warm run's smallest cache read per request is 18,373 tokens larger than on Direct API. On a warm cache they cost little; a cold run first has to write them to the cache. 593 of 600 runs started warm. The 7 cold ones are the first run of each model and setup, and one more (Sonnet 5.5 on Direct API, started 308 s after the previous run of its model and setup had ended).

Cost, MCP ÷ Direct API

0 0.5 1 1.5 ← MCP lower MCP higher → Haiku 5.5 Haiku 5.5, cost, warm: median ÷ median = 0.31 (0.29–0.32) 0.31 (0.29–0.32) Haiku 5.5, cost, cold: first MCP run ÷ first Direct API run = 0.49 (one run each) 0.49 Sonnet 5.5 Sonnet 5.5, cost, warm: median ÷ median = 0.76 (0.73–0.79) 0.76 (0.73–0.79) Sonnet 5.5, cost, cold: first MCP run ÷ first Direct API run = 1.41 (one run each) 1.41 Opus 5.5 Opus 5.5, cost, warm: median ÷ median = 0.56 (0.55–0.59) 0.56 (0.55–0.59) Opus 5.5, cost, cold: first MCP run ÷ first Direct API run = 1.11 (one run each) 1.11

Time, MCP ÷ Direct API

0 0.5 1 1.5 ← MCP lower MCP higher → Haiku 5.5 Haiku 5.5, time, warm: median ÷ median = 0.35 (0.33–0.36) 0.35 (0.33–0.36) Haiku 5.5, time, cold: first MCP run ÷ first Direct API run = 0.38 (one run each) 0.38 Sonnet 5.5 Sonnet 5.5, time, warm: median ÷ median = 0.68 (0.67–0.69) 0.68 (0.67–0.69) Sonnet 5.5, time, cold: first MCP run ÷ first Direct API run = 0.80 (one run each) 0.80 Opus 5.5 Opus 5.5, time, warm: median ÷ median = 0.62 (0.58–0.66) 0.62 (0.58–0.66) Opus 5.5, time, cold: first MCP run ÷ first Direct API run = 0.69 (one run each) 0.69
Same scale as above; dashed line at 1. A first run counts as cold when its least-read model request read no more than the lowest per-request cache read of any run of its model and setup. Data: study/data/exploratory.json (cold_start), from study/data/cache/min-request-cache-read.json and study/data/cache/pilot-root-spans.json; warm ratios from study/data/analysis.json.

Cold against cold, MCP cost Sonnet 5.5 and Opus 5.5 more, and still saved for Haiku 5.5; all three cold runs finished sooner on MCP. One run per model and setup is an observation, not a result.

SetupCost, first runCost, medianCache write, first run (tokens)Cache write, median (tokens)
Haiku 5.5
MCP$0.0105$0.006734,0279,254
Direct API$0.0214$0.021945,92141,028
Sonnet 5.5
MCP$0.1403$0.077432,2618,069
Direct API$0.0996$0.101617,25915,548
Opus 5.5
MCP$0.2730$0.173331,7737,978
Direct API$0.2449$0.308420,66223,654
The first run of each model and setup against the median of its 100 runs. Data: study/data/exploratory.json (cold_start.cells).

How it ran

Limits

Reproduce

The rows, spans, analysis output and the frozen harness are in study/ on this branch. To recompute every number from the rows, with uv:

git clone -b gh-pages https://github.com/pedro-angel/mcp-for-kibana.git mcp-savings-study
cd mcp-savings-study/studies/mcp-savings/study/harness
uv run python mcp_savings_analyze.py analyze --phase study \
  --rows ../data/rows.jsonl --harness-sha 9d4ec85 --out /tmp/mcp-savings
uv run python mcp_savings_explore.py --phase study \
  --rows ../data/rows.jsonl --harness-sha 9d4ec85 --out /tmp/mcp-savings \
  --spans ../data/spans/spans.jsonl \
  --min-reads ../data/cache/min-request-cache-read.json \
  --pilot-rows ../data/cache/pilot-root-spans.json
cmp /tmp/mcp-savings/analysis.json ../data/analysis.json
cmp /tmp/mcp-savings/exploratory.json ../data/exploratory.json
cd ../.. && python3 study/build_site.py   # rebuilds this page

How the rows were pulled from Honeycomb: study/docs/PULL_ROWS.md. What each file is: study/README.md.