Files
znetsixe 6e6699c763 tools: add physics-sanity + Docker MCP scaffolding + tools/README
- tools/physics-sanity/ — JS library of cross-node balance helpers
  (mass / hydraulic / hydraulic-power / oxygen-transfer / energy) with
  7 unit tests + a CLI demo. Designed for `require()` from per-node
  integration tests where shape-based unit tests miss physically-
  impossible plant states.
- tools/docker-compose.yml + tools/mcp/{node-red-admin,influxdb,browser}
  scaffolding — placeholder Dockerfiles + a ROADMAP.md for the Node-RED
  admin MCP. Compose file is the target shape for the Q3-2026 migration
  to the central MCP server; the per-service Dockerfile stays in this
  repo as the canonical definition either way. Implementations are TODO.
- tools/README.md — top-level tooling index; documents the CI order for
  running every tool on a PR.
- .gitignore: ignore tools/.env (developer-specific MCP endpoints).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 10:16:47 +02:00
..

EVOLV MCP services — Docker stack

Three MCP services Claude Code uses to close real loops during EVOLV work:

Service What it does Tools exposed
mcp-node-red-admin Wraps the Node-RED HTTP admin API getFlows, postFlow, getFlow, inject, listNodes, restartFlow
mcp-influxdb Queries the telemetry bucket query, assertSeriesExists, assertRecentWrite, listMeasurements
mcp-browser Headless Playwright against the FlowFuse dashboard loadDashboard, screenshot, consoleLogs, waitForChart, getChartData

Why these

Each closes a verification loop Claude currently cannot close:

  • Node-RED admin — today Claude pushes flows via raw curl; the MCP lets Claude deploy + fire injects + read live state in one conversational turn.
  • InfluxDB — today Claude cannot verify "did the telemetry land?" beyond reading source. The MCP closes the loop after a deploy.
  • Browser — today Claude cannot see the rendered dashboard. The MCP catches the failure mode behind the η-null crash + the blank-ui-chart bug + the editor pile-up bug at the only layer where they're visible.

Migration plan

These run locally now (we're in the middle of an infra migration). Once the central MCP server is provisioned (target Q3 2026), each service moves to shared infra by lifting the entry from this docker-compose.yml plus the matching tools/mcp/<name>/Dockerfile and pointing every developer's Claude Code at the central endpoint instead of localhost. The compose file stays here as the canonical definition.

Usage

# build the three images (one-off, ~3 min)
cd tools
docker compose --profile mcp build

# start them
docker compose --profile mcp up -d

# wire Claude Code to them — add to your user-level .mcp.json
{
  "mcpServers": {
    "evolv-node-red-admin": { "type": "stdio", "command": "docker", "args": ["exec", "-i", "evolv-mcp-node-red-admin", "node", "server.mjs"] },
    "evolv-influxdb":       { "type": "stdio", "command": "docker", "args": ["exec", "-i", "evolv-mcp-influxdb",       "node", "server.mjs"] },
    "evolv-browser":        { "type": "stdio", "command": "docker", "args": ["exec", "-i", "evolv-mcp-browser",        "node", "server.mjs"] }
  }
}

The repo-level .mcp.json is deliberately not committed (each developer has different host endpoints / tokens). Use a user-level config or ~/.claude.json.

Required environment

tools/.env (gitignored) with:

NODE_RED_HOST=http://host.docker.internal:1880
NODE_RED_TOKEN=…           # optional, only if Node-RED has admin auth on
INFLUX_URL=http://host.docker.internal:8086
INFLUX_TOKEN=…
INFLUX_ORG=wbd
INFLUX_BUCKET=telemetry
DASHBOARD_URL=http://host.docker.internal:1880/dashboard

Status

Service Dockerfile Server impl Status
mcp-node-red-admin placeholder TODO — see mcp/node-red-admin/ROADMAP.md not runnable yet
mcp-influxdb placeholder TODO not runnable yet
mcp-browser placeholder TODO — wrap @playwright/test not runnable yet

The compose file is the target shape. The Dockerfile + server implementation per service is a follow-up (each is ~200400 LOC of MCP protocol + the wrapped client). When a service lands, flip its row above to runnable and remove the placeholder.

When to use these — required reading

CLAUDE.md § "Tooling (Docker-first, local now, central later)" lists the operating doctrine: always prefer these tools over ad-hoc curl/grep/manual checks. Each tool exists because of a specific bug class we've already paid for. Skipping them re-opens those bugs.

Future: OPC-UA / PLC MCP

Out of scope for this round; will be revisited later. When added it follows the same pattern: tools/mcp/opcua/ with its own Dockerfile and a row in this README.