Run the full-site example
From git clone to a live site with multiple Workers and mock hardware
Overview
This tutorial presents the full-site example end to end running the full MDK stack: multiple configured Workers across a range of device families, their mock device servers, a Gateway HTTP API, and a React dashboard, all in one command.
What you'll have at the end:
- The supported fleet: multiple miner types, container types, and power meters; one sensor family with two inlet sensors; and two mining pools, each backed by mock hardware that speaks the real wire protocol
- A Gateway API at
:3007serving/site/overview,/site/history, and/site/miners/:id/command - A React dashboard at
:3040with live hashrate, power, and device status - An MCP server exposing the site's device registry, telemetry, and commands as tools for AI agents
The example can boot in one Node.js process (node start.js) or as separate processes through an interactive REPL (node cli.js).
This tutorial uses start.js — the simplest path.
Prerequisites
- Node.js >=24 (LTS)
- npm >=11
Install the example
1.1 Clone the repo
git clone git@github.com:tetherto/mdk.git
cd mdk1.2 Run setup
cd examples/full-site
npm run setupsetup installs backend/core, backend/workers, the UI workspace devkit packages, and this example's own dependencies. It runs once; subsequent
starts skip it.
The script walks several workspaces; first run takes 1-2 minutes.
Start the site
Start with a small fleet (3 miners per family, 9 total) for a fast first boot:
node start.js --miners 3Wait for the terminal to print the Gateway and UI URLs:
Gateway http://localhost:3007
UI http://localhost:3040Open http://localhost:3040 in a browser. The dashboard shows live hashrate, total power, and a per-device breakdown.
Verify via the API:
curl -s http://localhost:3007/site/overview | jq '{miners: (.miners|length), containers: (.containers|length), pools: (.pools|length), sensors: (.sensors|length)}'Expected output:
{
"miners": 9,
"containers": 2,
"pools": 2,
"sensors": 2
}The default fleet (100 miners per family, 300 total) opens 900+ file descriptors simultaneously. Before switching from --miners 3 to the full
fleet, run ulimit -n 4096 in the same terminal session.
What just happened
- Setup installed
backend/core,backend/workers, the MDK UI devkit, and this example — all the packagesstart.jsimports at boot. - Mock hardware —
mocks.jsstarted one server per device family (miners on TCP, containers on HTTP and MQTT, power meters and sensors on Modbus, pools on REST). They speak the real wire protocols; every Worker driver runs its true connect, collect, and command paths against them. - Kernel —
getKernel()started the orchestration layer that discovers Workers as they register and routes telemetry pulls and commands to them. - Workers — eleven
bootWorker()calls, one per configured Worker spec, each dispatching to that family'sstart{X}Worker()boot function (startWhatsminerWorker,startAvalonWorker, ...) to construct aWorkerRuntimeand connect it to the Kernel. - Gateway —
startGateway()mounted the site plugin fromplugins/site/and opened the HTTP server on:3007. The plugin aggregates data across the configured Workers throughmdkClient. - UI — a Vite React dev server started on
:3040, serving a dashboard built from MDK devkit components. - MCP server — an MCP server started over HRPC, exposing the site's device registry, telemetry, and command dispatch as tools for AI agents.
Cleanup
Ctrl+C stops mocks, Workers, Kernel, Gateway, and the UI dev server cleanly.
State (Kernel key, Worker seeds, device registry, and tail-log history) persists in .mdk-data/. To wipe it:
rm -rf examples/full-site/.mdk-dataNext steps
- If Kernel, Gateway, Worker, manager, or thing are unfamiliar, read terminology
- Run the same supported Worker fleet under PM2 or Docker — Multi-process deployment guide
- Add custom plugins to the Gateway HTTP API
- Connect an AI agent to the MCP server to query and command the site
- Explore the interactive CLI process manager for per-process logs, runtime seeding, and live status