Documentation Index
Fetch the complete documentation index at: https://mintlify.com/deeplethe/forkd/llms.txt
Use this file to discover all available pages before exploring further.
forkd-mcp is a stateless Model Context Protocol server that wraps the forkd-controller REST API as MCP tools. Once registered, any MCP-aware client — Claude Desktop, Claude Code, Cursor, Cline — can spawn Firecracker microVMs, exec commands inside them, branch a running sandbox into a new snapshot, and fan out grandchildren, all from natural language. The server itself holds no state; every tool call hits the forkd-controller daemon fresh, and the daemon owns sandbox lifecycle. Running forkd-mcp requires a forkd-controller daemon already running on the host.
Installation
Client configuration
- Claude Desktop
- Claude Code
- Cursor
- Cline
Add to Restart Claude Desktop. The forkd tools appear in the “hammer” menu.
~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows):Available MCP tools
The server exposes eleven tools, each mapping 1:1 to a forkd-controller REST endpoint.list_snapshots
List parent snapshots registered with the forkd controller. Returns SnapshotInfo objects: tag, dir, created_at_unix.
No parameters.
spawn_sandboxes
Fork N children from a parent snapshot.
Name of a registered snapshot (see
list_snapshots).Number of children to spawn, 1–1000.
When
true, each child is placed in a per-child network namespace forkd-child-<i>. The host must have run scripts/netns-setup.sh N first.Cgroup
memory.max for each child in MiB.When
true, the daemon performs a throwaway snapshot immediately after restore to fault in all guest pages. Trades ~170 ms / 512 MiB of extra spawn time for predictable BRANCH latency on the first user-visible BRANCH. Useful when you have a BRANCH SLO and fan out 3+ sandboxes from the same source.v0.4+. Boots the sandbox with a memfd-backed RAM region so later
branch_sandbox calls can use mode="live" (UFFD_WP). Requires kernel 5.7+ and the vendored Firecracker fork.Spawned sandbox objects, one per child. Each contains
id, pid, guest_addr, snapshot_tag, netns, created_at_unix, and memory_limit_mib.branch_sandbox
Branch a running sandbox into a new snapshot. This is forkd’s core primitive: pause the source briefly, snapshot its memory and vCPU state, then resume. The resulting snapshot can be used as snapshot_tag in any future spawn_sandboxes call — fan out N children that all inherit the source’s exact state at branch time.
Id of the source sandbox (see
list_sandboxes).Optional name for the new snapshot. When unset the daemon generates
branch-<sandbox-id>-<unix-ts>.v0.4+ canonical mode selector. One of
"full", "diff", or "live". Prefer this over the legacy diff boolean."full"— copy entire guest RAM (0.5–8 s pause). Default."diff"— Firecracker Diff snapshot (v0.3+). ~200 ms idle source; 6–15× faster on typical agent workloads."live"— UFFD_WP (v0.4+). Sub-50 ms source pause; requires source spawned withlive_fork=True. Mutually exclusive withdiff.
Legacy. Equivalent to
mode="diff". Kept so the server can drive v0.3.x daemons that don’t understand mode. Mutually exclusive with mode.Measurement-only hook. Takes a Diff snapshot inside the existing Full pause to report what diff would have cost, without changing semantics.
v0.4+, only meaningful with
mode="live". Default True blocks until the background copy finishes (status="ready"). Set to False to return after the source resumes (~10 ms); poll list_snapshots until status="ready".tag, dir, pause_ms, and status when mode="live".create_snapshot
Build a parent snapshot from a kernel and rootfs. Boots a fresh VM with the given kernel + rootfs, waits boot_wait_secs for the guest to settle, snapshots it, and registers it under tag.
Name to register the snapshot under (alphanumeric + dash/underscore, 1–64 chars).
Host path to a
vmlinux kernel image.Host path to a rootfs image (
.ext4 for writable, .squashfs for read-only).When
true, mount the rootfs read-write. Auto-enabled for .ext4 paths.Optional host tap device to attach as guest
eth0 (create with scripts/host-tap.sh).Seconds to wait for the guest to settle before snapshotting. Increase to 30+ for snapshots that need to warm up large Python packages.
The registered snapshot. Durable across daemon restarts.
list_sandboxes
List currently-alive child sandboxes.
No parameters.
All live sandboxes the daemon tracks.
get_sandbox
Fetch metadata about one sandbox by id.
The sandbox id to inspect.
Full metadata for the sandbox.
exec_command
Run a subprocess inside a sandbox.
The target sandbox id.
Argv list (e.g.
["python3", "-c", "print(2+2)"]).Maximum seconds to wait for the command.
{"stdout": str, "stderr": str, "exit_code": int}eval_code
Evaluate a Python expression against the sandbox’s warmed PID-1. The parent VM already imported numpy, torch, etc.; eval_code returns in single-digit milliseconds instead of ~100 ms for a fresh subprocess.
The target sandbox id.
Python expression to evaluate. Pre-imported packages are in scope.
{"result": Any, "error": str | None, "exit_code": int}wait_for_text
Poll a file inside a sandbox until it contains a marker string. Common pattern: an agent writes its progress to a log file inside the guest; the orchestrator polls until a marker like "READY_TO_BRANCH" appears, then triggers branch_sandbox.
The target sandbox id.
Absolute path inside the guest of the file to poll.
Substring to wait for.
Maximum wall-clock seconds to wait.
How often to re-check in milliseconds.
{"found": bool, "elapsed_ms": int, "last_excerpt": str}. When found is false, last_excerpt contains the last ~256 bytes of the file so you can see what was actually written.ping_sandbox
Round-trip to the in-guest agent. Returns its health and runtime info.
The target sandbox id.
Health and version info from the in-guest agent.
kill_sandbox
Terminate one sandbox. Kills the Firecracker process and removes its cgroup leaf.
The sandbox id to terminate.
{"id": str, "killed": true}Environment variables
Base URL of the forkd-controller daemon. Override when the daemon runs on a non-default port or a remote host.
Bearer token for the controller daemon. Required when the daemon was started with
--token-file. Read the token from /etc/forkd/token on Linux installs: sudo cat /etc/forkd/token.Per-request HTTP timeout in seconds. Branching a large VM can take several seconds; increase this on slow storage.
Smoke test
Example: Claude branching an agent mid-thought
Onceforkd-mcp is registered, Claude can orchestrate the full branch-and-fan-out pattern from a single conversation. A typical session looks like this:
- Claude calls
list_snapshotsto discover available parent templates (e.g.langgraph-react). - Claude calls
spawn_sandboxeswithlive_fork=Trueto boot a source sandbox with memfd-backed RAM. - Claude calls
exec_commandrepeatedly to run the agent’s warmup steps inside the sandbox. - Claude calls
wait_for_texton a progress file, blocking until the agent writes"READY_TO_BRANCH". - Claude calls
branch_sandboxwithmode="live"andwait=False— source pause is sub-50 ms, Claude returns in ~10 ms. - Claude polls
list_snapshotsuntil the branch snapshot showsstatus="ready". - Claude calls
spawn_sandboxeswith the branch tag andn=3, then injects a different steering hint into each child viaexec_command. - Claude calls
kill_sandboxto tear down the source and all children when done.
Prerequisites
forkd-mcp is a thin proxy — it holds no VM state itself. The forkd-controller daemon must be running and reachable at FORKD_URL for any tool call to succeed. See the forkd quick start for daemon setup and the operator runbook for production deployment.- Linux x86_64 with KVM (
/dev/kvmaccessible) forkd-controllerdaemon running (systemd unit atpackaging/systemd/forkd-controller.service)- At least one registered snapshot (
forkd pull deeplethe/langgraph-reactorforkd from-image python:3.12-slim --tag mysnap) - For
mode="live"BRANCH: Linux kernel 5.7+,vm.unprivileged_userfaultfd=1, and the vendored Firecracker fork