Kyle Isom d56f224359 Add unikernel runtime: run services as Nanos VMs under QEMU/KVM
Implements the hypervisor design's Phase 1: a second runtime.Runtime
backend (QEMU) that runs each service component as a Nanos unikernel VM
instead of a podman container, selected per-component via a new
runtime = "unikernel" service-def field.

- internal/runtime/qemu.go: QEMURuntime. Pull extracts the ELF from the
  OCI image; Run does `ops build` + boots qemu-system-x86_64 with KVM,
  user-mode net port-forwards, QMP control socket and serial console log;
  Stop/Remove/Inspect/List/Logs map onto VM lifecycle + state dir.
- proto/registry/servicedef: add runtime, memory_mb, vcpus fields
  (registry migration 5).
- agent: holds both runtimes; runtimeFor() selects per component;
  listAllContainers() merges containers + VMs so drift/status see both.
  Unikernel runtime auto-enables on nodes with /dev/kvm + ops.

Validated end-to-end on straylight: a test service deploys via
`mcp deploy --direct`, boots as a Nanos unikernel, serves HTTP through
the agent port-forward, and reports running via `mcp status`/`mcp logs`.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-11 00:54:49 -07:00
2026-03-26 22:46:36 -07:00
2026-03-30 17:46:12 -07:00

MCP — Metacircular Control Plane

MCP is the orchestrator for the Metacircular platform. It manages container lifecycle, tracks what services run where, and transfers files between the operator's workstation and managed nodes.

Architecture

CLI (mcp) — thin client on the operator's workstation. Reads local service definition files, pushes intent to agents, queries status.

Agent (mcp-agent) — per-node daemon. Manages containers via rootless podman, stores a SQLite registry of desired/observed state, monitors for drift, and alerts the operator.

Quick Start

Build

make all          # vet, lint, test, build
make mcp          # CLI only
make mcp-agent    # agent only

Install the CLI

cp mcp ~/.local/bin/
mkdir -p ~/.config/mcp/services

Create ~/.config/mcp/mcp.toml:

[services]
dir = "/home/<user>/.config/mcp/services"

[mcias]
server_url   = "https://mcias.metacircular.net:8443"
service_name = "mcp"

[auth]
token_path = "/home/<user>/.config/mcp/token"

[[nodes]]
name = "rift"
address = "100.95.252.120:9444"

Authenticate

mcp login

Check status

mcp status    # full picture: services, drift, events
mcp ps        # live container check with uptime
mcp list      # quick registry query

Deploy a service

Write a service definition in ~/.config/mcp/services/<name>.toml:

name = "myservice"
node = "rift"
active = true

[[components]]
name = "api"
image = "mcr.svc.mcp.metacircular.net:8443/myservice:v1.0.0"
network = "mcpnet"
user = "0:0"
restart = "unless-stopped"
ports = ["127.0.0.1:8443:8443"]
volumes = ["/srv/myservice:/srv/myservice"]
cmd = ["server", "--config", "/srv/myservice/myservice.toml"]

Then deploy:

mcp deploy myservice

Commands

Command Description
mcp login Authenticate to MCIAS
mcp deploy <service>[/<component>] Deploy from service definition
mcp stop <service> Stop all components
mcp start <service> Start all components
mcp restart <service> Restart all components
mcp list List services (registry)
mcp ps Live container check
mcp status [service] Full status with drift and events
mcp sync Push all service definitions
mcp adopt <service> Adopt running containers
mcp service show <service> Print spec from agent
mcp service edit <service> Edit definition in $EDITOR
mcp service export <service> Export agent spec to file
mcp push <file> <service> [path] Push file to node
mcp pull <service> <path> [file] Pull file from node
mcp node list List nodes
mcp node add <name> <addr> Add a node
mcp node remove <name> Remove a node

Documentation

Description
No description provided
Readme 43 MiB
2026-03-27 08:34:37 +00:00
Languages
Go 98.8%
Shell 0.7%
Nix 0.3%
Makefile 0.2%