elastic / elastic/example-mcp-app-observability

Server starts silently when ELASTICSEARCH_URL/ELASTICSEARCH_API_KEY are missing — only fails on first tool call

Open
#11 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
16
Forks
8
PR merge metrics
No merged PRs in 30d

Description

## Summary

If a user runs the MCP app server without configuring `ELASTICSEARCH_URL` and `ELASTICSEARCH_API_KEY`, **the server starts up successfully and all tools register** — but every tool invocation fails with `ELASTICSEARCH_URL and ELASTICSEARCH_API_KEY environment variables are required`. The diagnosis only surfaces inside an opaque tool-error path, not at startup.

## Steps to reproduce

```bash
unset ELASTICSEARCH_URL ELASTICSEARCH_API_KEY KIBANA_URL KIBANA_API_KEY
node dist/main.js
# or
node dist/main.js --stdio
```

Server logs:
```
Elastic Observability MCP App server running on http://localhost:3001/mcp
```

…and waits for connections. Nothing in the logs indicates that no tool can actually function. When an LLM eventually calls a tool, the failure surfaces deep in the request pipeline as an unhelpful generic error.

## Expected

One of:
1. **Hard failure at startup** — `createServer()` (or `main.ts`) calls `getConfig()` and exits non-zero with a clear `Missing ELASTICSEARCH_URL / ELASTICSEARCH_API_KEY` message.
2. **Loud warning at startup** — server still starts (useful for the npx-on-first-launch path where Claude Desktop hasn't yet plumbed env vars), but logs a prominent warning that all tools will fail until creds are supplied.
3. **Skill-gap-style notice on tool failure** — wrap the missing-config exception so the tool response includes a structured `_setup_notice` pointing the user at the credential docs (analogous to the existing skill-gap pattern in `src/setup/skill-check.ts`).

Option 1 is cleanest. Option 2 is friendlier for the install paths where the server gets started before user-config substitution completes (Claude Desktop). Option 3 surfaces the diagnosis inside the host UI without crashing.

## Actual behavior

- `main.ts:42` starts the HTTP server (or stdio transport) without ever calling `getConfig()`.
- `src/server.ts` registers tools without validating creds — only checks `isKibanaConfigured()` to decide whether to register `manage-alerts`.
- The throw in `src/elastic/client.ts:40-44` only fires when a tool calls `esRequest()` → `getConfig()` for the first time.
- Result: the failure is hidden until tool-invocation time, and the error text isn't necessarily surfaced cleanly to the user (depends on host-side error rendering).

## Affected install paths

- Most acute on the npx / VS Code / Cursor paths where the user hand-edits a JSON config — easy to forget a key and see no immediate signal.
- Less common on the Claude Desktop `.mcpb` path, since Claude Desktop's `manifest.json` declares the env vars as `user_config` and prompts the user. (And the `cleanEnv` helper in `client.ts:18-22` already handles the un-substituted-placeholder case there.)

## Suggested fix area

`createServer()` in `src/server.ts` or the entry path in `main.ts` should call `getConfig()` (or a validate-only helper) at startup. For HTTP mode this can happen once at `app.listen()` time; for stdio it happens before `server.connect(transport)`.

Bonus: surface the same check via the existing `_setup_notice` infrastructure so when a user *does* hit the failure mid-conversation (e.g., creds expired), the UI banner explains it instead of the LLM having to interpret an opaque error.

## Severity

Low/Medium. Doesn't break working installs, but it makes diagnosis hard for first-time users — exactly the audience least equipped to read a stack trace.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.