mcp-devops-dashboard
Provides monitoring of Docker container status via docker ps and remediation actions such as restarting Docker containers (e.g., docker start postgres-dev) through the MCP server.
Forwards remediation events to an n8n webhook for external automation when the agent executes an environment fix.
Uses a local Ollama instance (qwen2.5-coder:7b) as the autonomous remediation agent, calling it with a tool schema to decide and execute environment fixes based on live telemetry.
Provides remediation actions for Redis services, such as restarting Redis instances via the MCP server's execute_environment_fix tool.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@mcp-devops-dashboardcheck system health and show any degraded services"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
MCP Event-Driven DevOps Engine
A local infrastructure monitor that watches host resource usage and service health, streams live telemetry to a React dashboard over SSE, and dispatches a local LLM (via Ollama) as an autonomous remediation agent when it detects degraded services — with an MCP server exposing the same monitoring/remediation tools to any MCP-compatible client (Claude Desktop, etc.).
Problem
Local dev environments (Docker containers, Postgres, Redis, a dev API) drift out of a healthy state silently — a container dies, a port stops responding, cache grows unbounded — and you find out only when something downstream breaks. This project is a self-contained proof of concept for closing that loop: detect degradation, hand it to an LLM agent with a constrained tool surface, let it decide and execute a safe fix, and make the whole cycle observable.
Related MCP server: WEATHGARDS
Architecture
┌─────────────────┐ poll every 4s ┌──────────────────────┐
│ Host / Docker │ ─────────────────▶ │ mcp-server (Node) │
│ (CPU, RAM, │ │ - Express API │
│ ports, docker) │ │ - SSE broadcaster │
└─────────────────┘ │ - SQLite history │
│ - MCP tool server │
└─────────┬────────────┘
│ spawn (on degraded state)
▼
┌──────────────────────┐
│ agent.ts │
│ Ollama (qwen2.5- │
│ coder:7b) tool-call │
│ against real │
│ telemetry snapshot │
└─────────┬────────────┘
│ POST /api/agent-remediate
▼
┌──────────────────────┐
│ react-dashboard │
│ Vite + React + │
│ Tailwind + Recharts │
│ (live via SSE) │
└──────────────────────┘mcp-server (mcp-server/) — Node/TypeScript/Express.
Polls host CPU/RAM (
os.cpus()), local port health (net.Socketconnect checks on 5173/5432), and Docker status (docker ps) every 4 seconds.Persists metrics history and logs to SQLite (
telemetry.db), keeping a sliding window (last 50 log rows, last 50 metric snapshots).Broadcasts every tick to connected dashboards via Server-Sent Events (
/events).Exposes an MCP server over stdio (
@modelcontextprotocol/sdk) with three tools:get_system_status,read_environment_logs,execute_environment_fix— so any MCP client, not just this dashboard, can query or remediate the same environment.On detecting a degraded service (with a 30s cooldown to prevent cascading agent spawns), it spawns
agent.tsas a child process, passing the real live metrics snapshot as an argument.
agent.ts (mcp-server/src/agent.ts) — the autonomous remediation step.
Calls Ollama (
qwen2.5-coder:7b) with a proper tool schema (execute_environment_fix) and reads back structuredtool_callsfrom the response — not string-matching on free text.The prompt is built from the actual telemetry snapshot passed in (which services are degraded, current CPU/RAM/cache), not a hardcoded scripted alert.
On a valid tool call, POSTs the chosen action back to the server's
/api/agent-remediateendpoint, which executes it (e.g.docker start postgres-dev), and optionally forwards a remediation event to an n8n webhook for external automation.
react-dashboard (react-dashboard/) — Vite + React 19 + TypeScript + Tailwind + Recharts.
Live CPU/RAM/cache tiles, a rolling telemetry area chart, per-service health tiles (api/database/docker_containers), a diagnostic log stream, and a manual "Force Manual Audit" trigger — all driven by the SSE stream with an initial REST fetch on load.
Client-side anomaly heuristic (CPU up 25%+ over the last 4 snapshots) surfaces a predictive warning independently of the backend agent.
A real finding from the eval harness
First run of npm run eval:full against qwen2.5-coder:7b (Ollama 0.32.5) scored 6/20 — every
case that should have produced a tool call instead produced none. The raw model output showed
the model reasoning correctly almost every time (e.g. {"name": "execute_environment_fix", "arguments": {"action": "restart_postgres"}}) but emitting it as plain text in
message.content instead of Ollama's structured tool_calls field, which decide() was only
reading from the structured field. Confirmed the model itself wasn't the problem
(ollama show qwen2.5-coder:7b lists tools as a supported capability) before changing
anything.
Fix: agentCore.decide() now falls back to strict JSON-schema validation against the model's
raw text only when the structured field comes back empty — not the substring-matching approach
the original agent.ts used. One case (elevated cache, no degraded service) surfaced a genuine
hallucination — the model invented a tool name (report_nominal_status) that isn't in the
schema — which the fallback correctly treats as "no valid action" rather than accepting it.
After that fix, back-to-back runs of the same 20 cases scored differently (16/20, then 15/20)
with no code changes between them — Ollama's default sampling isn't deterministic, so a single
eval run's score wasn't trustworthy on its own. Pinned temperature: 0.
With temperature pinned, the score became reproducible — and revealed something a varying score
had been masking: every "all healthy, no action needed" case deterministically produced
clear_cache anyway, regardless of the actual cache number, while every real degraded-service
case was correct. The prompt had been asking the model to judge whether a cache number was
"far above normal" — a numeric threshold decision an LLM shouldn't be trusted to make reliably
when code can make it deterministically instead. Fix: describeSituation() now computes whether
cache is elevated (CACHE_ELEVATED_THRESHOLD_MB = 100) in code and tells the model an
unambiguous conclusion — "cache is elevated, call clear_cache" or "cache is nominal, do NOT call
any tool" — rather than a number and a vague instruction to reason about it.
After all five fixes (structured-field fallback, multi-shape JSON parsing, markdown-fence
stripping, pinned temperature, deterministic cache-threshold check), npm run eval:full scores
20/20 against qwen2.5-coder:7b. 14 of those 20 still go through the fallback text parser —
this model reliably reasons correctly but has not been observed emitting Ollama's structured
tool_calls field even once across ~80 calls made while building this harness, so the fallback
path is load-bearing, not a rare edge case.
Tradeoffs / design decisions
SQLite over a real time-series DB: sufficient at this scale (single host, 50-row sliding window), avoids an extra service dependency for a local tool.
Polling (4s) over OS-level event hooks: simpler, portable across platforms; costs responsiveness for very short-lived failures between ticks.
Cooldown-gated agent spawn (30s) instead of a queue: prevents cascading agent loops when multiple services degrade at once, at the cost of possibly missing a fix window if a new issue appears mid-cooldown.
Local LLM (Ollama) over hosted API: zero marginal cost and no data leaving the host, at the cost of weaker reasoning than a frontier hosted model — mitigated by keeping the tool surface small and explicit rather than relying on open-ended reasoning.
Separate child process per agent run rather than an in-process call: isolates a slow or hung model call from the main event loop and dashboard responsiveness.
Known limitations
Remediation actions (
restart_redis,restart_postgres,clear_cache) are a fixed, small action set — this is intentionally scoped as a proof of concept, not a general-purpose ops agent.No test suite yet; the mcp-server
testscript is a placeholder.n8n webhook forwarding degrades silently if n8n isn't running locally — this is expected in a standalone demo, but worth knowing before assuming remediation events are always externally visible.
Evals
mcp-server/src/evals/ scores the remediation agent's decisions against 20 synthetic
telemetry scenarios (cases.ts) — single degraded services, multiple simultaneous
degradations, healthy-but-high-resource states, and a no-data edge case.
Two stages, run via npm run eval (or npm test) inside mcp-server/:
Prompt-construction check (always runs, no LLM call, no Ollama required) — verifies
describeSituation()actually surfaces the facts the model needs (which service is degraded, current CPU/RAM/cache) for every case. Deterministic, safe for CI.Full LLM-graded run (
npm run eval:full) — calls the real model viaagentCore.decide()withexecute: false(scores the decision, fires no docker restarts or webhooks) and checks whether the returned tool call matches the expected action. Requires a local Ollama instance runningqwen2.5-coder:7b.
Note on ground truth: the degraded-service cases have an unambiguous correct action. The
cache-threshold cases (e.g. "150MB, no degraded service, should call clear_cache") encode
a judgment call rather than a hard rule, since the system prompt intentionally leaves the
threshold fuzzy ("elevated," "far above normal") rather than hardcoding a number — worth
knowing before treating a miss on those specific cases as a regression.
Running it
Requires Ollama running locally with qwen2.5-coder:7b pulled, and
Docker running if you want the docker-status check and postgres remediation to do anything real.
# terminal 1 — MCP/API server
cd mcp-server
npm install
npm start
# terminal 2 — dashboard
cd react-dashboard
npm install
npm run devDashboard: http://localhost:5173. API/SSE: http://localhost:3001.
This server cannot be deployed
Maintenance
Related MCP Connectors
MCP server for AI agents to plan, verify, and deploy Cloudflare-native apps.
- UnifAPIOAuthcom.unifapi
Hosted MCP server for live public-data APIs and Skills for AI agents.
Remote MCP server for supportsheep: run AI interviews and manage support content for your blog.
Real-time planetary signal engine and Model Context Protocol (MCP) server for autonomous AI agents.
Related MCP Servers
- AlicenseNot gradedqualityAmaintenanceSelf-hosted AI orchestrator that monitors and manages homelab services, exposing them as MCP tools for LLMs to drive.2MIT
- FlicenseNot gradedqualityDmaintenanceExposes MCP tools that enable remote LLMs to query local Docker containers, OS processes, and system services in real time.-
- AlicenseNot gradedqualityFmaintenanceMulti-machine system monitor with a built-in MCP server that enables AI agents to query health metrics, manage processes, schedule cron jobs, and run diagnostics across local and remote machines.133 npmApache 2.0
- AlicenseBqualityDmaintenanceMCP server that gives Claude Code real-time visibility into local infrastructure — Docker containers and system health.21MIT