# pyro-mcp `pyro-mcp` is a Firecracker-backed sandbox for coding agents. It exposes the same runtime in two public forms: - a `pyro` CLI - a Python SDK via `from pyro_mcp import Pyro` It also ships an MCP server so LLM clients can use the same VM runtime through tools. ## Start Here - Install: [docs/install.md](/home/thales/projects/personal/pyro/docs/install.md) - Host requirements: [docs/host-requirements.md](/home/thales/projects/personal/pyro/docs/host-requirements.md) - Integration targets: [docs/integrations.md](/home/thales/projects/personal/pyro/docs/integrations.md) - Public contract: [docs/public-contract.md](/home/thales/projects/personal/pyro/docs/public-contract.md) - Troubleshooting: [docs/troubleshooting.md](/home/thales/projects/personal/pyro/docs/troubleshooting.md) ## Public UX Primary install/run path: ```bash uvx --from pyro-mcp pyro mcp serve ``` Installed package path: ```bash pyro mcp serve ``` The public user-facing interface is `pyro` and `Pyro`. `Makefile` targets are contributor conveniences for this repository and are not the primary product UX. Check the installed CLI version: ```bash pyro --version ``` ## Repository Storage This repository uses Git LFS for the packaged runtime images under `src/pyro_mcp/runtime_bundle/`. Fresh contributor setup: ```bash git lfs install git clone cd pyro git lfs pull make setup ``` The large files tracked through LFS are: - `src/pyro_mcp/runtime_bundle/**/rootfs.ext4` - `src/pyro_mcp/runtime_bundle/**/vmlinux` If you are working from an older clone created before the LFS migration, reclone or realign your branch to the rewritten history before doing more work. ## Capabilities - Firecracker microVM execution with bundled runtime artifacts - standard profiles: - `debian-base` - `debian-git` - `debian-build` - high-level one-shot execution via `vm_run` / `Pyro.run_in_vm(...)` - low-level lifecycle control when needed: - `vm_create` - `vm_start` - `vm_exec` - `vm_stop` - `vm_delete` - `vm_status` - `vm_network_info` - `vm_reap_expired` - outbound guest networking with explicit opt-in ## Requirements - Linux host - `/dev/kvm` - Python 3.12+ - host privilege for TAP/NAT setup when using guest networking The current implementation uses `sudo -n` for `ip`, `nft`, and `iptables` when networked runs are requested. ## CLI Start the MCP server: ```bash pyro mcp serve ``` Run one command in an ephemeral VM: ```bash pyro run --profile debian-git --vcpu-count 1 --mem-mib 1024 -- git --version ``` Run with outbound internet enabled: ```bash pyro run --profile debian-git --vcpu-count 1 --mem-mib 1024 --network -- \ "git clone --depth 1 https://github.com/octocat/Hello-World.git hello-world && git -C hello-world rev-parse --is-inside-work-tree" ``` Show runtime and host diagnostics: ```bash pyro doctor ``` Run the deterministic demo: ```bash pyro demo pyro demo --network ``` Run the Ollama demo: ```bash ollama serve ollama pull llama:3.2-3b pyro demo ollama ``` Verbose Ollama logs: ```bash pyro demo ollama -v ``` ## Integration Examples - Python one-shot SDK example: [examples/python_run.py](/home/thales/projects/personal/pyro/examples/python_run.py) - Python lifecycle example: [examples/python_lifecycle.py](/home/thales/projects/personal/pyro/examples/python_lifecycle.py) - MCP client config example: [examples/mcp_client_config.md](/home/thales/projects/personal/pyro/examples/mcp_client_config.md) - OpenAI Responses API example: [examples/openai_responses_vm_run.py](/home/thales/projects/personal/pyro/examples/openai_responses_vm_run.py) - Agent-ready `vm_run` example: [examples/agent_vm_run.py](/home/thales/projects/personal/pyro/examples/agent_vm_run.py) ## Python SDK ```python from pyro_mcp import Pyro pyro = Pyro() result = pyro.run_in_vm( profile="debian-git", command="git --version", vcpu_count=1, mem_mib=1024, timeout_seconds=30, network=False, ) print(result["stdout"]) ``` Lower-level lifecycle control remains available: ```python from pyro_mcp import Pyro pyro = Pyro() created = pyro.create_vm( profile="debian-git", vcpu_count=1, mem_mib=1024, ttl_seconds=600, network=True, ) vm_id = created["vm_id"] pyro.start_vm(vm_id) result = pyro.exec_vm(vm_id, command="git --version", timeout_seconds=30) print(result["stdout"]) ``` The recommended agent-facing default is still one-shot execution through `run_in_vm(...)` / `vm_run`. Use lifecycle methods only when the agent needs VM state to persist across multiple calls. ## MCP Tools Primary agent-facing tool: - `vm_run(profile, command, vcpu_count, mem_mib, timeout_seconds=30, ttl_seconds=600, network=false)` Advanced lifecycle tools: - `vm_list_profiles()` - `vm_create(profile, vcpu_count, mem_mib, ttl_seconds=600, network=false)` - `vm_start(vm_id)` - `vm_exec(vm_id, command, timeout_seconds=30)` - `vm_stop(vm_id)` - `vm_delete(vm_id)` - `vm_status(vm_id)` - `vm_network_info(vm_id)` - `vm_reap_expired()` ## Runtime The package ships a bundled Linux x86_64 runtime payload with: - Firecracker - Jailer - guest kernel - guest agent - profile rootfs images No system Firecracker installation is required. Runtime diagnostics: ```bash pyro doctor ``` The doctor report includes: - runtime integrity - component versions - capability flags - KVM availability - host networking prerequisites ## Contributor Workflow For work inside this repository: ```bash make help make setup make check make dist-check ``` Runtime build and validation helpers remain available through `make`, including: - `make runtime-bundle` - `make runtime-materialize` - `make runtime-boot-check` - `make runtime-network-check` Space cleanup after runtime work: ```bash rm -rf build git lfs prune ``` Recreating `.venv/` is also a straightforward way to reclaim local disk if needed.