The integration model
What MDK can be extended with, and by which of its two extension points
Two extension points, named after what they extend
| Worker plugin | Gateway plugin | |
|---|---|---|
| Extends | The Worker tier | The Gateway tier |
| Declares itself with | mdk-contract.json (the Worker contract) | mdk-plugin.json |
| That declaration is read by | Kernel today (routing, validation); the UI and agents are intended readers, not wired up yet | The Gateway loader (routes, auth flag) |
| Job | Speak one device family's native protocol; expose it as telemetry + commands | Add an HTTP route: aggregate, authenticate, or otherwise sit between a caller and @tetherto/mdk-client |
The naming is literal: a Worker plugin is a plugin for a Worker, a Gateway plugin is a plugin for the Gateway. Neither extends Kernel: Kernel has no plugin system, by design (see Architecture).
The contract: one file, three intended audiences
A Worker plugin's mdk-contract.json is designed to be read by three different consumers, so there's one
source of truth instead of three:
- Kernel reads
capabilities.commands[]today to validate that a command a caller sends is one the Worker actually declared, and to route by device family for write-permission checks (miner:w,container:w). - The UI is meant to read the same telemetry/command names and units to label a value without hard-coding a device's vocabulary. Not wired up today: the UI code that ships in this repo hard-codes its own labels and units rather than reading them from a contract.
- An AI agent is meant to read the same contract at runtime to derive its tool set. Not wired up today: MCP
tools come from a static, author-written
mcp-plugin.jsonmanifest, or are auto-generated from a Gateway plugin's HTTP routes — neither path reads a Worker'smdk-contract.json(see the MCP server).
This is the intended contract architecture, not current runtime behavior for the UI and agent halves — only Kernel's command validation actually reads the contract today.
mdk-plugin.json gets the same treatment, for Gateway plugins
A Gateway plugin's manifest declares its routes (id, handler, http.method/http.path, response schema,
constraints, examples, errors, safety). The Gateway's plugin loader reads it to mount routes and validate the
manifest shape at load time; nothing about it is hand-wired into the Gateway's own code path per plugin.
Workers are not only hardware
A Worker plugin wraps whatever answers to "one device, one connection, one set of telemetry/commands"; that's just as often a non-hardware integration:
- A pool API Worker: telemetry is your hashrate/earnings from the pool's own API, "commands" might be switching workers between pools; no physical device involved at all.
- An accounting sync Worker: telemetry is a ledger balance or a sync status pulled from a third-party service, with no ASIC anywhere in the picture.
Both get the exact same treatment from Kernel as a physical miner: identity, capabilities, telemetry pull, command dispatch. Kernel does not know or care that there is no hardware behind either one.
What this buys you
Write the integration once (one Worker plugin per device family, one Gateway plugin per route you need) and every consumer built against the standard round trip works with it for free: the same dashboard code, the same agent tooling, the same Gateway auth model, regardless of which device family or which route it's actually talking to underneath.
Contract versioning today
There is no enforced compatibility mechanism between contract versions today. A Worker plugin's mdk-contract.json
has no version field of its own: the package's package.json semver is the only version signal, and nothing in
Kernel or the Gateway checks it against a caller's expectations. In practice this means: a contract's shape is
whatever the currently-loaded plugin declares, and there's no compatibility gate protecting a caller written
against an older shape. If a contract's telemetry or command names change, that's a breaking change for anything
built against the old names, with no automated warning today.
Next steps
- Build a Worker plugin for a new device family
- Understand the Gateway plugin authoring flow
- Understand the storage model: what a Worker plugin decides to persist
- Understand architecture: where both extension points sit in the round trip
Next steps
- Build a Worker plugin for a new device family
- Understand the storage model
- Understand architecture