runtime serves its seat's verbs (novox/hq ADR 0159) A module on several machines served one subject in one queue group, so a call reached whichever instance answered first and nobody could ask one machine's instance. Now each instance also serves its subject with its machine as the last token, `<module>.<tool>@<node>` addresses it, and every answer carries the machine that gave it: the console lists `node` on every module tool, strips it into the subject, and appends "answered by <node>" to the answer; `mesh call` prints it. And a seat's verbs are served by whoever claims the seat: the credential names the claimed seats and the verbs each promises, the runtime serves each verb with the module's tool of the same name on the seat's own subject, and the bus — which admits only the holder's subscription — decides where that serving is real. Design 33 §3 and §4, built.
mesh-tools
The Novox Mesh tool runtime — the per-node process that makes a module's tools actually serve.
A module ships its tools (built on @novox/mesh-sdk); this
runtime is what loads them and puts them on the mesh. It:
- connects the mesh broker (novox/hq ADR 0001) — a concrete AMQP implementation of the sdk's
Brokercontract; - imports the assigned modules' compiled tool entrypoints, each of which registers its tools as it loads;
- serves them through the sdk's
serveToolsharness, answeringtools.invokeover the broker.
Everything hard — dispatch, collection, duplicate-name safety — is the sdk's. This is the thin wrapper that binds the broker and loads the modules. Keeping the AMQP client here, out of the sdk, is deliberate: a broker-client change never rebuilds a module (ADR 0039).
Running it
MESH_BROKER_URL amqp://… the mesh broker
MESH_TOOL_MODULES /a/tools/index.js,… the assigned modules' compiled tool entrypoints
node dist/main.js, or the container (Dockerfile). On a node the host resolves both variables
and starts it like any other supervised workload.
mesh — the tools for whoever is on a machine
The same package carries the client (novox/hq design 25 §7, design 34): mesh tools, mesh call <module>.<tool> [json], mesh mcp (an MCP server over stdio for a program a person starts) and
mesh serve (the console: MCP over HTTP on a machine's loopback, started by the mesh as the
mesh-console module on the credential in MESH_BROKER_FILE — novox/hq ADR 0152). mesh serve
refuses to bind anything but loopback. With --console <url>, tools and call go through a console
already on the machine and need no credential.
Discovery asks the modules: every runtime answers a tools verb for each module it serves, with names,
descriptions and schemas from the code that answers them, and the console asks the catalogue which
modules the mesh holds and each module what it serves. A module that does not answer is named, never
dropped. A module may not name a tool of its own tools; the runtime refuses it at load.
Verified
npm test stands up LavinMQ (the mesh's broker) and proves the whole path over real AMQP: the
runtime serves a registered tool, a separate connection invokes it by name and gets the result, and
an unknown tool is refused over the wire.