feat: MCP integration for AI tools#1156
Conversation
There was a problem hiding this comment.
Pull request overview
Adds documentation and container-side scaffolding to support Model Context Protocol (MCP) integrations so AI coding tools can query LGTM data (traces/metrics/logs/dashboards), plus an optional OpenTelemetry Collector debug-exporter overlay.
Changes:
- Document MCP setup and add a new MCP integration guide.
- Enable Tempo’s MCP server and emit an MCP config JSON (including a Grafana service-account token) from the container.
- Add an opt-in OTEL Collector “debug exporter” overlay and extend acceptance test log expectations.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
| README.md | Adds a short “AI Tool Integration (MCP)” entry point and MCP link. |
| docs/mcp-integration.md | New guide describing MCP setup, including Grafana + Tempo MCP configuration. |
| docker/run-all.sh | Generates Grafana service account token and writes /etc/lgtm/mcp.json, plus startup log hints. |
| docker/tempo-config.yaml | Enables Tempo MCP server in the query frontend. |
| docker/run-otelcol.sh | Adds OTEL_COLLECTOR_DEBUG_EXPORTER flag to layer an extra collector config. |
| docker/otelcol-config-debug.yaml | New overlay config that adds debug exporters to traces/metrics/logs pipelines. |
| examples/python/oats.yaml | Extends acceptance test to assert the new MCP-related startup log lines. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
7168471 to
c676495
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 8 out of 8 changed files in this pull request and generated 3 comments.
Comments suppressed due to low confidence (1)
docker/run-otelcol.sh:43
- When both OTEL_EXPORTER_OTLP_ENDPOINT (adds otelcol-config-export-http.yaml) and OTEL_COLLECTOR_DEBUG_EXPORTER (adds otelcol-config-debug.yaml) are enabled, the later debug config replaces the pipelines'
exporterslists, which dropsotlphttp/externaland stops exporting to the external OTLP endpoint. Consider generating a combined config (or a separate debug+external config) so the exporters list includes both debug/* and otlphttp/external when both flags are set (instead of last-one-wins).
debug_config_file=""
if [[ ${OTEL_COLLECTOR_DEBUG_EXPORTER:-false} == "true" ]]; then
echo "Enabling debug exporter for OpenTelemetry Collector"
debug_config_file="--config=file:./otelcol-config-debug.yaml"
fi
run_with_logging "OpenTelemetry Collector ${OPENTELEMETRY_COLLECTOR_VERSION}" "${ENABLE_LOGS_OTELCOL:-false}" \
./otelcol-contrib/otelcol-contrib --feature-gates service.profilesSupport --config=file:./otelcol-config.yaml ${secondary_config_file} ${debug_config_file}
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
2931a57 to
6c02cb7
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 9 out of 9 changed files in this pull request and generated 5 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 9 out of 9 changed files in this pull request and generated 7 comments.
Comments suppressed due to low confidence (2)
build-lgtm.sh:25
- This now prefers Podman over Docker when both are installed, but still unconditionally runs
buildx build. On many systemspodman buildxisn’t available by default, so this can break builds that previously succeeded with Docker. Consider checking forbuildxsupport (or falling back topodman build/ using Docker when available), or allow users to override the runtime selection.
if command -v podman >/dev/null 2>&1; then
RUNTIME=podman
elif command -v docker >/dev/null 2>&1; then
RUNTIME=docker
else
echo "Unable to find a suitable container runtime such as Docker or Podman. Exiting."
exit 1
fi
if [ "$RUNTIME" = "podman" ]; then
TAG="localhost/grafana/otel-lgtm:${RELEASE}"
else
TAG="grafana/otel-lgtm:${RELEASE}"
fi
$RUNTIME buildx build -f docker/Dockerfile docker --tag "$TAG" --build-arg LGTM_VERSION="${RELEASE}"
docker/run-otelcol.sh:43
- When both
OTEL_EXPORTER_OTLP_ENDPOINT(external export) andOTEL_COLLECTOR_DEBUG_EXPORTER=trueare set, this passes two extra--configfiles that both overrideservice.pipelines.*.exporters(otelcol-config-export-http.yamlandotelcol-config-debug.yaml). Depending on config merge precedence, the later file can clobber the earlier one, dropping the external exporter (or the debug exporter). Consider generating a combined exporters list (external + debug) or ensuring the overlay config doesn’t overwrite other overlays’ exporter settings.
debug_config_file=""
if [[ ${OTEL_COLLECTOR_DEBUG_EXPORTER:-false} == "true" ]]; then
echo "Enabling debug exporter for OpenTelemetry Collector"
debug_config_file="--config=file:./otelcol-config-debug.yaml"
fi
run_with_logging "OpenTelemetry Collector ${OPENTELEMETRY_COLLECTOR_VERSION}" "${ENABLE_LOGS_OTELCOL:-false}" \
./otelcol-contrib/otelcol-contrib --feature-gates service.profilesSupport --config=file:./otelcol-config.yaml ${secondary_config_file} ${debug_config_file}
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
20b37ab to
b31b1d7
Compare
- Auto-create Grafana service account and token at startup - Generate /etc/lgtm/mcp.json (mcp-grafana + Tempo native MCP) - Generate /etc/lgtm/claude-mcp-setup.sh for one-command Claude Code setup - Add opt-in collector debug exporter (OTEL_COLLECTOR_DEBUG_EXPORTER=true) - Enable Tempo MCP server, expose port 3200 - Add docs/mcp-integration.md
b31b1d7 to
44540db
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 8 out of 8 changed files in this pull request and generated 5 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Break long curl and otelcol commands to stay under 150 chars - Remove space before redirects (shfmt: `> file` → `>file`) - Fix heredoc body indentation for shfmt compliance
Integrate debug exporter config into main's array-based arg handling.
- Extract Grafana credentials and base URL into variables (martincostello) - Restrict file permissions on token and MCP config files (umask 077) - Fix README wording: clarify Grafana MCP is client-side, not in-container - Quote SA token in claude-mcp-setup.sh heredoc - Use GitHub URL instead of relative path in MCP docs output
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 8 out of 8 changed files in this pull request and generated 3 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
Keeping in draft - waiting for feedback from human testers |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 14 out of 14 changed files in this pull request and generated 6 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
@zeitlinger any plans to support some non-stdio transport for |
|
Btw, when running the mcp image - |
no, mcp-grafana is a process tool, stdio only by design that being said, I'd love to try out a CLI based approach too, but this is the first thing that's available |
… handling - Remove brittle MCP log assertions from oats.yaml (only printed when SA token creation succeeds, causing test failures on container restarts) - Clarify docs/mcp-integration.md: Tempo has an in-container HTTP MCP endpoint; Grafana uses a client-side uvx mcp-grafana process - Add --init to docker/podman run in run-lgtm.sh and run-lgtm.ps1 so ctrl-c properly forwards signals to container processes
Being a mcp and uvx noob, iiuc As such it makes a bit hard for use to wire it I guess, |
|
Ah, I've been told this is not true ... we could also start |
## Summary - Add `*.bats` to the shellcheck file pattern in `super-linter.sh` native mode ## Why Bats test files use bash syntax and shellcheck catches real issues in them (SC2034 unused variables, SC2314 bats-specific `!` usage, etc.). Docker super-linter already lints `.bats` files; native mode was missing the glob pattern, creating a gap where CI catches issues that local `native-lint` misses. Discovered while fixing shellcheck errors in [grafana/docker-otel-lgtm#1156](grafana/docker-otel-lgtm#1156). The same fix is applied to `run-linters.sh` in #136. ## Test plan - [ ] `mise run test` passes
Replace bash parameter expansion one-liner with a readable two-liner. Add kubectl exec equivalent for Kubernetes users in MCP setup section.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 13 out of 13 changed files in this pull request and generated 5 comments.
Comments suppressed due to low confidence (1)
README.md:265
- The README now documents port-forwarding Tempo on 3200 and suggests
mise k8s-port-forwardas an alternative, but thek8s-port-forwardtask inmise.tomlstill forwards only3000 4040 4317 4318 9090(no3200). This makes the mise shortcut inconsistent with the documented port-forward command; consider updating the mise task to include3200:3200as well.
# Configure port forwarding
kubectl port-forward service/lgtm 3000:3000 3200:3200 4040:4040 4317:4317 4318:4318 9090:9090
# Using mise
mise k8s-apply
mise k8s-port-forward
</details>
---
💡 <a href="/grafana/docker-otel-lgtm/new/main?filename=.github/instructions/*.instructions.md" class="Link--inTextBlock" target="_blank" rel="noopener noreferrer">Add Copilot custom instructions</a> for smarter, more guided reviews. <a href="https://docs.github.com/en/copilot/customizing-copilot/adding-repository-custom-instructions-for-github-copilot" class="Link--inTextBlock" target="_blank" rel="noopener noreferrer">Learn how to get started</a>.
|
Put in draft mode - I want to try GCX first |
- run-lgtm.sh: explicitly pass OTEL_COLLECTOR_DEBUG_EXPORTER so `OTEL_COLLECTOR_DEBUG_EXPORTER=true ./run-lgtm.sh` works as documented - docker/run-all.sh: extract GRAFANA_SA_URL variable to avoid repeating the base URL across all service-account API calls - docs/mcp-integration.md: add podman exec alternative to TOKEN line
@martincostello as discussed - let's do this PR before trying out a new approach |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 13 out of 13 changed files in this pull request and generated 3 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
martincostello
left a comment
There was a problem hiding this comment.
Looks OK to me modulo the GitHub Copilot comments.
…p.sh - mise.toml: k8s-port-forward task was missing 3200:3200 even though the README documents it in the manual kubectl command - docker/run-all.sh: quote -e arguments in the generated claude-mcp-setup.sh so URLs with special chars don't break the claude mcp add invocation
|
@zeitlinger is there a new image version already out with this cool mcp stuff? |
|
These changes should be in v0.24.0. |
Closes #1091
Summary
/etc/lgtm/mcp.jsonat startup — one config block for any MCP clientOTEL_COLLECTOR_DEBUG_EXPORTER=truedocs/mcp-integration.mdSetup
docker exec lgtm cat /etc/lgtm/mcp.jsonPaste into your AI tool's MCP configuration.
Test plan
mcp.jsonis generated with valid SA tokenOTEL_COLLECTOR_DEBUG_EXPORTER=true, verify debug output in logs