Ops & agents
MCP server design
An MCP server that gives AI agents the full VM lifecycle through 21 tools that mirror the CLI and the API.
flash-mcp is the Model Context Protocol server for FlashVMM: a JSON-RPC 2.0 process on the MCP stdio transport that gives an AI agent the whole FlashVM lifecycle through 21 tools mapped one to one onto the flash CLI and the OpenAPI-described REST resources of flashvm, flashpoold, flashhostd, flashgpud and flash controller.
One source crate (flash-mcp-core) carries the tool contract (names, input schemas and descriptions), and each operating system's flash-mcp binary supplies its native transport: Unix sockets on Linux and macOS, named pipes on Windows. An agent learns one tool set and drives every platform with it. Every tool description is written for a model: it states the exact arguments, the reply shape and the next tool to call. See MCP for what agents do with it.
Key facts
| Runs on | Linux (x86_64, arm64), macOS (Apple silicon), Windows (x64, arm64); one tool contract on all of them |
|---|---|
| Interfaces | MCP tools/list · tools/call · notifications/progress · backed by the CLI and REST |
| Tools | 21 |
| Protocol | JSON-RPC 2.0, one message per line on stdin/stdout; protocolVersion 2024-11-05; capability tools |
| Transport to a FlashVM | HTTP/1.1 over the VM's own Unix socket (Linux, macOS) or named pipe (Windows) |
flash_cli timeout | 120 s per call; argv passed as an array, no shell |
flash_exec defaults | timeout_s 300; output kept up to 16 MiB per stream |
| Fan-out | flash_watch_fleet merges up to 20 FlashVM streams |
How it works
A thin, faithful layer
flash-mcp holds no state of its own. The MCP client starts it as a child process; it answers initialize, lists its tools on tools/list, and turns each tools/call into exactly the request an operator's flash would make. Results come back as MCP tool results, with isError set from the real outcome and the daemon's own error body carried through unchanged.
Three kinds of tool
- Create and destroy through the real binary.
flash_cliruns the installedflashwith an argv array. Creation (run,restore,clone,fork) goes through the same code path an operator uses (spawning the flashvm process with its capability drops, userfaultfd detection on Linux and registry locking), so an agent gets identical VMs and identical behavior. - Typed per-VM tools.
flash_ls,flash_inspect,flash_metrics,flash_diagnose,flash_logs,flash_exec,flash_cp,flash_diff,flash_connections,flash_secret_proxy_calls,flash_sleep,flash_wakeandflash_resourceeach name one job with a structured reply (for exampleflash_execreturns{exit_code, signal, state, stdout, stderr, duration_ms, truncated}).flash_apisends any method to a running VM's REST API for every write the typed tools leave to it, such asPATCH /v1/flashvm/nics/{i}orPUT /v1/flashvm/workload. - Daemon tools with route allowlists.
flash_pool(flashpoold, warm pools),flash_host(flashhostd, the host),flash_gpu(flashgpud) andflash_controller(the controller) each send one request to their daemon. Each tool checks method and path against the routes in that daemon's OpenAPI document, segment by segment, before anything is sent; a test keeps the list equal to the spec.
Streaming
flash_watch opens one of a VM's server-sent event streams — metrics, logs, lifecycle or guest_messages — and emits one MCP notifications/progress message per event against the call's progressToken while the call is in flight. flash_watch_fleet runs the same watch for up to 20 VMs on parallel threads and prefixes each message with its FlashVM id; every stdout write takes its own short lock, so concurrent streams interleave cleanly.
Per-platform transport
Each OS uses its native local IPC: Linux and macOS reach each flashvm and each daemon over a Unix socket (flashpoold at /run/flashpoold.sock, flashhostd at /run/flashhostd.sock, flashgpud at /run/flashgpud.sock by default on Linux); Windows uses named pipes, and the tools' address argument is named pipe there. The descriptions are localized at tools/list time so the model reads its own platform's addresses.
Interfaces
CLI
# register flash-mcp with an MCP client as a stdio server, then drive it; the same work by hand:
flash run --bundle /opt/flashvm/bundles/current --vcpus 2 --mem-mib 1024 --egress public --id agent1 --detach
flash exec agent1 -- sh -c 'uname -a'
flash checkpoint agent1
flash fork agent1 --count 3
flash connections agent1
MCP
flash_cli(args: ["run", "--bundle", "/opt/flashvm/bundles/current", "--vcpus", "2", "--mem-mib", "1024", "--egress", "public", "--id", "agent1", "--detach"])
flash_exec(vm_id: "agent1", argv: ["sh", "-c", "pip install requests"], changes: true, checkpoint: true)
flash_diff(a: "agent1", b: "agent1-fork1")
flash_watch(vm_id: "agent1", stream: "lifecycle")
flash_watch_fleet(vm_ids: ["agent1", "agent2"], stream: "metrics")
flash_pool(method: "POST", path: "/v1/vm-pools", body: {"shape": {"vcpus": 1, "mem_mib": 256}, "count": 8})
flash_host(method: "GET", path: "/v1/host")
REST
flash_api(vm_id: "agent1", method: "PATCH", path: "/v1/flashvm/nics/0", body: {"egress": "allow:pypi.org,*.pythonhosted.org"})
flash_api(vm_id: "spare-3", method: "PUT", path: "/v1/flashvm/workload", body: {"entry": "/app/run", "entry_arg": []})
Contract an agent relies on:
flash_watch_fleetrejects a request for more than 20 ids as a whole.- A daemon tool rejects a method and path outside that daemon's OpenAPI routes before sending it.
flash_wakeon a VM that slept with a NIC returnsnic_missinguntilnicis given.flash_cli run --enginewith an engine the host lacks returns 422unsupported_engine.- A claim returns once accepted; poll
flash_inspectforentry_startedandstate.
Guarantees
- One contract. The same 21 tool names, schemas and replies on Linux, macOS and Windows.
- Same path as the operator. Agents create VMs through the installed
flashbinary, so every VM is built exactly as the CLI builds it. - No injection surface. Commands travel as argv arrays; no shell string is ever interpolated.
- Spec-bound daemon calls. Daemon requests are checked against each daemon's OpenAPI routes before they leave.
- Live progress. Event streams arrive as standard MCP progress notifications while the call runs.