homelab-evidence-mcp
Read-only stdio MCP server that correlates homelab incident evidence across Gatus, Docker, Loki, Healthchecks, Beszel, and ntfy. Destinations locked at startup; HTTP GET only; timelines stay factual without inventing root cause.
Install
Install and configure the MCP from https://github.com/ThomasCrouzet/homelab-evidence-mcp now. Follow the repository's installation instructions, ask me for anything you can't complete yourself, and verify its tools load.homelab-evidence-mcp
This local MCP server uses stdio transport. It collects incident evidence from a homelab. The server is a static Go binary. It has no mutation operations.
Why
When a service has a failure, each source contains different signals:
- Gatus gives an error.
- Docker shows a container in the
restartingstate. - Loki contains a timeout from some moments before the failure.
- Healthchecks gives a scheduled job failure.
Each source tool gives data from one source. The tools do not use the same service identities, evidence formats, or timelines. This project correlates the data. It does not identify a cause.
Principles
The project uses these principles:
- Canonical service registry: A
service_idconnects Gatus, Docker, Loki, Healthchecks, Beszel, and ntfy identities. - Common evidence model: The model adds a source and two timestamps to each item. It also redacts data and uses limits. It shows truncation.
- Deterministic correlation: The timeline presents facts. It does not identify a root cause.
- Read-only operation: The server sends only HTTP
GETrequests. Destinations cannot change after startup.
Short example:
02:12 Loki upstream timeout [REDACTED]
02:13 Docker container media is restarting
02:14 Gatus media/app failure status=503
02:15 Healthchecks "media-cron" is down
The timeline uses observed_at order. Correlation does not identify a root cause.
This server is not a dashboard, an HTTP proxy for general use, or a control plane. It does not start containers again or identify root causes.
Installation
Prerequisite: Go 1.25 is the minimum version.
go install github.com/ThomasCrouzet/homelab-evidence-mcp/cmd/homelab-evidence-mcp@latest
To build from the repository:
make build
./bin/homelab-evidence-mcp --version
Quick start
Do these steps:
- Copy
config.example.yamlto a directory that is not in the repository. - Make sure that only its owner can access the file. On Unix, use
chmod 600 /path/config.yaml. On Windows, use a user-only ACL. - Add URLs for the internal network and some pilot services.
- Set the necessary tokens as environment variables, for example
HEALTHCHECKS_API_TOKEN. - Validate the configuration before you add it to the MCP client.
homelab-evidence-mcp --config /path/config.yaml --validate
Validation loads tokens from the YAML settings. Destinations cannot change
after this step. Validation sends no HTTP requests to these destinations.
Validation gives an error for each unknown YAML key. A base_url cannot
contain query strings, fragments, or userinfo.
Authentication uses token_env or token_file.
Registration with an MCP client:
{
"mcpServers": {
"homelab-evidence": {
"command": "/path/homelab-evidence-mcp",
"args": ["--config", "/path/config.yaml"],
"env": {
"HEALTHCHECKS_API_TOKEN": "readonly-key"
}
}
}
}
The server uses standard output only for the JSON-RPC protocol. It writes logs and audit events to standard error. See MCP client configuration and the integration example.
Source adapters
The server has these source adapters:
- Gatus: The adapter uses
GET /api/v1/endpoints/statuses. It selects the result with the greatest timestamp. - Docker Engine: The adapter uses
GET /containers/json?all=true. It filters fields and does not includeConfig.Env. - Loki: The adapter uses
GET /loki/api/v1/query_range. The configuration supplies the selector. - Healthchecks: The adapter uses
GET /api/v3/checks/. It uses a read-only key and does not include ping URLs in its output. - Beszel: The adapter uses
GET /api/systemsand compatible routes. It can give a host snapshot. - ntfy: The adapter uses
GET /{topic}/json?poll=1&since=<unix>. The configuration supplies the topic.
Destinations use only http and https. For Docker, use a read-limited socket
proxy. The Docker Unix socket is not compatible with the server. The server
ignores HTTP_PROXY and HTTPS_PROXY.
You can use a path prefix in base_url. For example, use
https://proxy.example/gatus for Gatus. The server keeps /gatus before each
Gatus API route.
The source response cache keeps responses to the same requests for a short
time.
Set the cache TTL with limits.source_cache_ttl. The default is 15s. A value
of 0 deactivates the cache.
The cache does not store clear-text authentication values in its keys. A
process-local HMAC fingerprint identifies each access secret. On a cache hit,
observed_at keeps the initial collection time. The retrieved_at field gives
the time of this read. Thus, freshness shows the age of the snapshot.
MCP tools
The server has these MCP tools:
evidence_capabilitiesgives the version, active sources, limits, and statistics.list_servicesgives services in the canonical service registry.service_statusgives a Gatus, Docker, Healthchecks, and Beszel snapshot.incident_contextgives a multi-source timeline with configuration limits.search_logsexamines Loki with the selector in the configuration.failed_cronsgives checks in thedown,grace, orpausedstate.get_evidencereads temporary evidence again by its opaque identifier.
All tool annotations identify the tools as read-only. Global limits control windows, HTTP body sizes, evidence counts, and concurrency.
Evidence model
Each evidence item contains its source and its observation and collection
timestamps. It also contains severity, freshness state, truncation, and the
redaction count. Responses give the ok, absent, skipped, error, and
timeout state of each source.
See the evidence model and tested API contracts.
Security
Read SECURITY.md for guarantees and remaining risks. The primary security controls are:
- Destinations cannot change after startup.
- The server does not accept HTTP redirects.
- MCP calls cannot supply a URL or stream selector.
- Log content is hostile data.
- The server uses built-in redaction and optional local rules.
- On Unix, give only the owner access to configuration and token files. Use
mode
0600. - On Windows, use a user-only ACL. The binary does not examine Windows ACLs.
Local demo
go run ./demo
The demo starts test HTTP servers and opens an in-memory MCP session. It
examines results when sources have errors and examines redaction. It also
makes sure that the server sends only GET requests. A homelab is not necessary.
Development
make test # tests with race detection
make test-quick # fast tests
make lint-docs # Markdown checks
make lint # formatting, go vet, and golangci-lint
make coverage
make build
CI builds Linux, macOS, and Windows binaries. The primary targets are headless Linux and macOS systems.
License
MIT. See LICENSE.
