MCP Shadow
Provides read-only tools to discover labelled Docker services, inspect container status and resource usage, read bounded logs, and generate differential reports across Docker homelab containers.
Adds optional local model-based analysis and advice alongside objective container observations using a configured Ollama endpoint and installed model.
This server does not currently have a deployable release on Glama. Follow the repository's setup instructions to install and configure it for your MCP client, including any required credentials and local dependencies.
MCP Shadow
Experimental project for a Docker homelab. Not production-ready.
MCP Shadow is a read-only Model Context Protocol server. It gives an MCP client or agent tools to discover labelled Docker services, query their status and resource usage, read bounded logs, and request differential reports. Optional local Ollama analysis adds advice alongside objective observations. It does not implement an autonomous agent or establish reliable incident causes.
Trust boundary: the included MCP HTTP endpoint has no authentication.
The Host and Origin checks protect against DNS rebinding. Compose publishes
the port on localhost by default. Labels filter access in the application; they
do not restrict direct Docker proxy access to individual containers. Logs,
raw snapshots, baselines and reports can contain sensitive data, even after redaction.
Use a trusted host/network and an authenticated gateway for remote access.
First query with synthetic data
Requirements: Linux Docker Engine with access to its local Unix socket, Docker Compose v2, a shell, and network access to fetch the pinned images and packages. You do not need Python on the host, an MCP desktop app, Ollama, or a model. Run from a clean copy of this directory:
bash scripts/run_integration.sh --demoThe script uses .env.example with ANALYSIS_PROVIDER=disabled. It starts a
labelled log fixture, the server and its Docker proxy in a temporary project with
its own internal network and state volume. Discovery is filtered to that project.
The official MCP Python SDK client connects over Streamable HTTP, queries the
fixture's state and memory, and observes 40 distinct generated error events across
report pages. It verifies pending report replay and acknowledges the pages. The
script removes the temporary containers, network and volume on exit.
The client prints a JSON summary like this. memory_percent depends on the host
and container, and objective_severity depends on the signals observed during
the query. A successful run observes 40 events and returns a null model advisory.
{
"client": "official MCP Python SDK",
"tools": 11,
"service": "log-fixture",
"state": "running",
"running": true,
"memory_percent": 0.01,
"synthetic": true,
"observed_error_events": 40,
"objective_severity": "medium",
"model_severity_advisory": null,
"delivery_replay_verified": true,
"checkpoint_acknowledged": true
}See the demo walkthrough for the MCP calls and the separate full integration check, which covers restart, disk full, log rotation, proxy outage and graceful degradation when Ollama is configured and unavailable.
Related MCP server: Docker Explorer
Why this exists
A homelab operator can ask an MCP client for observations across selected services without giving that client Docker command execution tools. The project explores MCP tool contracts, separation of observations from model advice, bounded log processing and recoverable report delivery. It demonstrates software engineering around tools an agent can consume; no scheduler, planning loop or autonomous remediation is included.
Install for your own homelab
Copy
.env.exampleto.env. For observation without a model, setANALYSIS_PROVIDER=disabled. Review the paths and keep the port on localhost.Prepare the default network and bind directories on Linux:
docker network create homelab-monitoring mkdir -p state disk-probe sudo chown 10001:10001 stateReuse an existing network if appropriate. The state directory must be writable by container UID 10001. Put
disk-probeon the filesystem to measure; it is mounted read-only. Adjust commands if you changed the example paths/network.Start a named project and check readiness:
docker compose -p shadow-lab up -d --build curl --fail http://127.0.0.1:8010/readyUse an MCP client with Streamable HTTP at
http://127.0.0.1:8010/mcp. For a reproducible query using the supplied client on a Python 3.14 host:python3.14 -m venv .venv .venv/bin/python -m pip install --require-hashes --only-binary=:all: -r requirements-hashed.txt .venv/bin/python scripts/mcp_demo.py --url http://127.0.0.1:8010/mcp \ --project shadow-lab --service mcp-shadowThis lists MCP tools and queries the server container's objective state and memory usage. A container client on the shared network can use
http://mcp-shadow:8000/mcp; use unique service aliases/networks if multiple stacks share that network. Removing fixed container names avoids host-global name conflicts, but shared-network DNS aliases still require care.
Streamable HTTP at /mcp accepts localhost, 127.0.0.1 and [::1] as
Host values without a port, with :8000, or with the published MCP_PORT
(8010 by default). It also accepts mcp-shadow:8000 for Compose clients.
The default Origin values are those same authorities prefixed by http://.
Native clients, including the official Python SDK client, can omit Origin.
For a custom DNS name, reverse proxy or Compose alias, add exact authorities to
MCP_ALLOWED_HOSTS (e.g. shadow-alias:8000,shadow.example) and, if the
client sends Origin, add exact origins to MCP_ALLOWED_ORIGINS (e.g.
https://console.example). Both variables add to the defaults. Include the port
when the client sends it. Origin values require a scheme and authority only.
Wildcards are unsupported. MCP_BIND_ADDRESS controls port publication and does
not add a trusted name. See the Streamable HTTP security requirements.
To observe another service, add labels to its Compose definition and recreate that service yourself:
labels:
io.shadowofintent.mcp.enabled: "true"
io.shadowofintent.mcp.name: "Example web service"
io.shadowofintent.mcp.description: "Synthetic example"
io.shadowofintent.mcp.log-profile: "nginx"
io.shadowofintent.mcp.expected-stopped: "false"Only enabled is required. list_managed_services returns the actual container
names for subsequent calls. Review ignore patterns in config/log-profiles.json;
filtering noise can hide relevant lines. Ollama is optional: configure an existing
trusted endpoint and installed model, then enable ANALYSIS_PROVIDER=ollama.
No model download is automatic.
Interface and report delivery
Tools | Observations or behavior |
| Runtime/system summary and monitored filesystem |
| Labelled services and container names |
| Selected container details, metrics and bounded log prefix |
| Objective signals with optional, fallible model advice |
| Differential reports and optional explicit confirmation |
The server://inventory resource describes capabilities; /health is liveness,
/ready checks Docker, writable state and the probe filesystem. Optional analysis
failure does not make objective tools unready. CPU/memory visibility depends on
the container environment; these are not guaranteed host-wide measurements.
For recoverable reports, request acknowledged_delivery=true, durably save/process
and deduplicate by delivery.id, then acknowledge that ID. Repeat until you
have acknowledged a report with baseline.complete_logs=true.
baseline.pending_pages counts captured streams with more pages to deliver and
can be zero even when capture failed.
When baseline.log_errors is nonzero, surface the failure, save and acknowledge
the delivery as usual, and request the next acknowledged report to retry capture
for the same interval. The acknowledgement can save partial progress while
keeping the interval open. The synthetic demo waits one second between attempts and
exits with an error after three consecutive capture failures. After restoring
capture, resume with the next acknowledged report on the same server state.
The interval keeps the original set of container identities. If a member is
removed or replaced before the interval is committed, the report stays incomplete.
The demo's in-memory storage is sufficient for its fixture. A real consumer
must persist the processed data and delivery IDs across restarts.
All clients share one pending report. A slow consumer blocks further report intervals. The default immediate-save mode can lose a page if its response is lost.
Snapshots capture the whole retained interval before paging: initial latency and disk use grow with that interval. Defaults cap snapshots at 256 MiB per container per interval and 1 GiB across the snapshot directory, with 64 MiB best-effort free space. Baseline and outbox files need extra space. Snapshots with saved cursors survive Docker rotation. Records removed before/during capture cannot always be detected or recovered; choose retention longer than the report interval. Local filesystem locking and atomic replacement are required. See the delivery, storage and recovery contract for concurrency and limits.
Evidence, limitations and project status
The API, schemas and on-disk state are experimental and may change. There is no stable compatibility promise. See verified builds and platforms for exact versions, dependency maintenance and untested platforms.
The Docker proxy permits selected GET endpoints on the host socket, including metadata/log access for unlabelled containers by a direct proxy client. It is not published to the host, but compromise of a container on its network matters. The read-only socket mount alone does not enforce read-only Docker requests. MCP has no authentication or per-user authorization. Raw log reads are not a privacy filter; best-effort model/report redaction cannot identify every secret. Treat local state and every output as sensitive and review before sharing.
Literal evidence validation cannot certify causes, safe advice or resistance to prompt injection. Recorded synthetic results include substantial failures: the corrected three-operation regression passed 8/18 narrow automated checks; the later development run passed 10/12 on different cases. Those scores are not comparable or production quality estimates. Human quality ratings remain pending (10 retained responses, 2 unreviewable rejections). Complete that review without running a model. No independent review or real incident evaluation is claimed.
The documentation index links to the development and publication guides, design decisions and evaluation history. The scripts index lists the commands and their inputs.
This server cannot be deployed
Maintenance
Related MCP Connectors
Ovanek MCP: Model Context Protocol server for Ovanek platform tools; writes are dry-run by default.
Model Context Protocol server for the Apideck Unified API. Connect any MCP-compatible agent framework to 100+ accounting systems, HRIS platforms, file storage providers, and more through one integration. More information https://www.apideck.com/mcp-server
Read-only MCP server that answers questions about turva.dev from its published data. Five tools return JSON: the service catalog with prices, contact and operator details, engagement principles and dated agent-readiness and security evidence with verification links. Connect over Streamable HTTP. You need no API key. The server does not scan other websites or run audits.
LLM cost optimization gateway, repo token-waste auditor & model arbitrage MCP server.
Related MCP Servers
- FlicenseAqualityFmaintenanceA Model Context Protocol server that enables Docker container management through natural language interactions using a custom GPT interface.715-
- AlicenseNot gradedqualityDmaintenanceA Model Context Protocol server that provides tools for interacting with Docker images, containers, and registries, enabling AI assistants to search, analyze, and manage Docker resources through a standardized interface.1MIT
- AlicenseBqualityBmaintenanceA Model Context Protocol server that provides seamless integration with Coroot observability platform, enabling monitoring of applications, analysis of performance metrics, examination of logs and traces, and management of infrastructure through Coroot's comprehensive API.6116MIT
- AlicenseBqualityCmaintenanceA portable, read-only Model Context Protocol server for turning observability data into bounded evidence that AI agents can inspect safely.7Apache 2.0