--- layer: as-is status: implemented code: [mesh-catalog modules/mesh-console, mesh-tools src/mesh.ts, mesh-tools src/http.ts, mesh-tools src/runtime.ts, mesh-controller internal/broker, mesh-controller cmd/mesh-controller/check.go, mesh-controller cmd/mesh-controller/seatverbs.go] updated: 2026-09-30 decisions: - 02-DECISIONS/0152-the-operators-surface-is-a-module-the-console.md - 02-DECISIONS/0095-the-control-plane-is-the-way-to-ask-a-module.md - 02-DECISIONS/0037-where-a-module-lives.md - 02-DECISIONS/0154-the-meshs-own-verbs-are-the-controller-seats-tools.md --- # The console, as it runs **The mesh's tools reach a person through a module the mesh assigned to their machine.** Since 2026-09-30 a workstation that is a node can be assigned `mesh-console`; the mesh mints a bus account `.mesh-console`, seals its credential to the machine, and the container binds `127.0.0.1:` with the port the mesh assigned for the manifest's declared one. An agent on the machine is pointed at `http://127.0.0.1:/mcp` and sees the mesh's tools; a person uses the same endpoint. Nothing on the machine holds a credential a person had to carry. ## What it answers `initialize`, `tools/list`, `tools/call`, over HTTP, one JSON body per request, no session and no event stream. `tools/list` is what the running modules answered: every tool runtime built on or after that day serves a `tools` verb for its module, and the console asks the catalogue for the roster and each module for its tools. A module that did not answer is named in the list's `_meta.notAnswering`. On the day it shipped that was 36 of 51 modules — those that serve no tools at all, and those whose rebuilt runtime the mesh records rather than rolls out — and 62 tools from the rest. `tools/call` reaches any tool by `.`, listed or not. The console's grant is `*`, so what it may call is every tool on the mesh; its account may publish nothing else and subscribes nothing. ## The mesh's own verbs *Since 2026-09-30 evening ([ADR 0154](../../02-DECISIONS/0154-the-meshs-own-verbs-are-the-controller-seats-tools.md)).* The console asks the `mesh-controller` seat's `tools` verb beside the modules and lists every role's tools as `.` — `mesh-controller.status`, `mesh-controller.push` and the other ten. A call to `.` reaches the seat when the prefix is a seat declaring that verb, and the module otherwise; `seat:.` says so outright. When the control plane does not answer, the list names `mesh-controller (seat)` as not answering and carries the modules' tools regardless. ## Around it - **`invokes`** in a manifest is the grant. It is composed into the bus's user list exactly as a person's account is; the console is the only module that declares it. - **`module check …`** on the controller's binary judges a manifest with no mesh: the strict parse, every per-manifest problem, and the rules between the manifests given. It prints what it cannot judge without a store rather than refusing. The console's own manifest was the first thing checked with it, and the whole catalogue passes. - **The person's client remains.** `operator issue` and `mesh tools|call|mcp` with a credential file still work, for a machine that is not a node and for a mesh not yet able to assign anything. `mesh tools --console ` goes through a running console with no credential; it is covered by the runtime repository's tests and was not exercised on the live mesh. ## What shipped bent - A module registered by hand from the catalogue with `--source --path modules/` records a URL, not a place on the git seat: `--self` takes the forge path form (`/`), which the operator did not pass. The rebuild-on-merge matched the URL anyway. - Modules whose upgrade policy is *record* — the forge among them — answered `tools` only once something pushed their rebuilt runtime; until then they are listed as not answering while still callable. That is the policy doing what it says, not a fault of the console.