pyro-mcp/docs/public-contract.md
Thales Maciel fc72fcd3a1 Add guest-only workspace secrets
Add explicit workspace secrets across the CLI, SDK, and MCP, with create-time secret definitions and per-call secret-to-env mapping for exec, shell open, and service start. Persist only safe secret metadata in workspace records, materialize secret files under /run/pyro-secrets, and redact secret values from exec output, shell reads, service logs, and surfaced errors.

Fix the remaining real-guest shell gap by shipping bundled guest init alongside the guest agent and patching both into guest-backed workspace rootfs images before boot. The new init mounts devpts so PTY shells work on Firecracker guests, while reset continues to recreate the sandbox and re-materialize secrets from stored task-local secret material.

Validation: uv lock; UV_CACHE_DIR=.uv-cache make check; UV_CACHE_DIR=.uv-cache make dist-check; and a real guest-backed Firecracker smoke covering workspace create with secrets, secret-backed exec, shell, service, reset, and delete.
2026-03-12 15:43:34 -03:00

12 KiB

Public Contract

This document defines the supported public interface for pyro-mcp 2.x.

Package Identity

  • Distribution name: pyro-mcp
  • Public executable: pyro
  • Public Python import: from pyro_mcp import Pyro
  • Public package-level factory: from pyro_mcp import create_server

CLI Contract

Top-level commands:

  • pyro env list
  • pyro env pull
  • pyro env inspect
  • pyro env prune
  • pyro mcp serve
  • pyro run
  • pyro workspace create
  • pyro workspace sync push
  • pyro workspace exec
  • pyro workspace export
  • pyro workspace diff
  • pyro workspace snapshot create
  • pyro workspace snapshot list
  • pyro workspace snapshot delete
  • pyro workspace reset
  • pyro workspace service start
  • pyro workspace service list
  • pyro workspace service status
  • pyro workspace service logs
  • pyro workspace service stop
  • pyro workspace shell open
  • pyro workspace shell read
  • pyro workspace shell write
  • pyro workspace shell signal
  • pyro workspace shell close
  • pyro workspace status
  • pyro workspace logs
  • pyro workspace delete
  • pyro doctor
  • pyro demo
  • pyro demo ollama

Stable pyro run interface:

  • positional environment name
  • --vcpu-count
  • --mem-mib
  • --timeout-seconds
  • --ttl-seconds
  • --network
  • --allow-host-compat
  • --json

Behavioral guarantees:

  • pyro run <environment> -- <command> defaults to 1 vCPU / 1024 MiB.
  • pyro run fails if guest boot or guest exec is unavailable unless --allow-host-compat is set.
  • pyro run, pyro env list, pyro env pull, pyro env inspect, pyro env prune, and pyro doctor are human-readable by default and return structured JSON with --json.
  • pyro demo ollama prints log lines plus a final summary line.
  • pyro workspace create auto-starts a persistent workspace.
  • pyro workspace create --seed-path PATH seeds /workspace from a host directory or a local .tar / .tar.gz / .tgz archive before the workspace is returned.
  • pyro workspace create --secret NAME=VALUE and --secret-file NAME=PATH persist guest-only UTF-8 secrets outside /workspace.
  • pyro workspace sync push WORKSPACE_ID SOURCE_PATH [--dest WORKSPACE_PATH] imports later host-side directory or archive content into a started workspace.
  • pyro workspace export WORKSPACE_ID PATH --output HOST_PATH exports one file or directory from /workspace back to the host.
  • pyro workspace diff WORKSPACE_ID compares the current /workspace tree to the immutable create-time baseline.
  • pyro workspace snapshot * manages explicit named snapshots in addition to the implicit baseline.
  • pyro workspace reset WORKSPACE_ID [--snapshot SNAPSHOT_NAME|baseline] recreates the full sandbox and restores /workspace from the chosen snapshot.
  • pyro workspace service * manages long-running named services inside one started workspace with typed readiness probes.
  • pyro workspace exec --secret-env SECRET_NAME[=ENV_VAR] maps one persisted secret into one exec call.
  • pyro workspace service start --secret-env SECRET_NAME[=ENV_VAR] maps one persisted secret into one service start call.
  • pyro workspace exec runs in the persistent /workspace for that workspace and does not auto-clean.
  • pyro workspace shell open --secret-env SECRET_NAME[=ENV_VAR] maps one persisted secret into the opened shell environment.
  • pyro workspace shell * manages persistent PTY sessions inside a started workspace.
  • pyro workspace logs returns persisted command history for that workspace until pyro workspace delete.
  • Workspace create/status results expose workspace_seed metadata describing how /workspace was initialized.
  • Workspace create/status/reset results expose reset_count and last_reset_at.
  • Workspace create/status/reset results expose safe secrets metadata with each secret name and source kind, but never the secret values.
  • pyro workspace status includes aggregate service_count and running_service_count fields.

Python SDK Contract

Primary facade:

  • Pyro

Supported public entrypoints:

  • create_server()
  • Pyro.create_server()
  • Pyro.list_environments()
  • Pyro.pull_environment(environment)
  • Pyro.inspect_environment(environment)
  • Pyro.prune_environments()
  • Pyro.create_vm(...)
  • Pyro.create_workspace(..., secrets=None)
  • Pyro.push_workspace_sync(workspace_id, source_path, *, dest="/workspace")
  • Pyro.export_workspace(workspace_id, path, *, output_path)
  • Pyro.diff_workspace(workspace_id)
  • Pyro.create_snapshot(workspace_id, snapshot_name)
  • Pyro.list_snapshots(workspace_id)
  • Pyro.delete_snapshot(workspace_id, snapshot_name)
  • Pyro.reset_workspace(workspace_id, *, snapshot="baseline")
  • Pyro.start_service(workspace_id, service_name, *, command, cwd="/workspace", readiness=None, ready_timeout_seconds=30, ready_interval_ms=500, secret_env=None)
  • Pyro.list_services(workspace_id)
  • Pyro.status_service(workspace_id, service_name)
  • Pyro.logs_service(workspace_id, service_name, *, tail_lines=200, all=False)
  • Pyro.stop_service(workspace_id, service_name)
  • Pyro.open_shell(workspace_id, *, cwd="/workspace", cols=120, rows=30, secret_env=None)
  • Pyro.read_shell(workspace_id, shell_id, *, cursor=0, max_chars=65536)
  • Pyro.write_shell(workspace_id, shell_id, *, input, append_newline=True)
  • Pyro.signal_shell(workspace_id, shell_id, *, signal_name="INT")
  • Pyro.close_shell(workspace_id, shell_id)
  • Pyro.start_vm(vm_id)
  • Pyro.exec_vm(vm_id, *, command, timeout_seconds=30)
  • Pyro.exec_workspace(workspace_id, *, command, timeout_seconds=30, secret_env=None)
  • Pyro.stop_vm(vm_id)
  • Pyro.delete_vm(vm_id)
  • Pyro.delete_workspace(workspace_id)
  • Pyro.status_vm(vm_id)
  • Pyro.status_workspace(workspace_id)
  • Pyro.logs_workspace(workspace_id)
  • Pyro.network_info_vm(vm_id)
  • Pyro.reap_expired()
  • Pyro.run_in_vm(...)

Stable public method names:

  • create_server()
  • list_environments()
  • pull_environment(environment)
  • inspect_environment(environment)
  • prune_environments()
  • create_vm(...)
  • create_workspace(..., secrets=None)
  • push_workspace_sync(workspace_id, source_path, *, dest="/workspace")
  • export_workspace(workspace_id, path, *, output_path)
  • diff_workspace(workspace_id)
  • create_snapshot(workspace_id, snapshot_name)
  • list_snapshots(workspace_id)
  • delete_snapshot(workspace_id, snapshot_name)
  • reset_workspace(workspace_id, *, snapshot="baseline")
  • start_service(workspace_id, service_name, *, command, cwd="/workspace", readiness=None, ready_timeout_seconds=30, ready_interval_ms=500, secret_env=None)
  • list_services(workspace_id)
  • status_service(workspace_id, service_name)
  • logs_service(workspace_id, service_name, *, tail_lines=200, all=False)
  • stop_service(workspace_id, service_name)
  • open_shell(workspace_id, *, cwd="/workspace", cols=120, rows=30, secret_env=None)
  • read_shell(workspace_id, shell_id, *, cursor=0, max_chars=65536)
  • write_shell(workspace_id, shell_id, *, input, append_newline=True)
  • signal_shell(workspace_id, shell_id, *, signal_name="INT")
  • close_shell(workspace_id, shell_id)
  • start_vm(vm_id)
  • exec_vm(vm_id, *, command, timeout_seconds=30)
  • exec_workspace(workspace_id, *, command, timeout_seconds=30, secret_env=None)
  • stop_vm(vm_id)
  • delete_vm(vm_id)
  • delete_workspace(workspace_id)
  • status_vm(vm_id)
  • status_workspace(workspace_id)
  • logs_workspace(workspace_id)
  • network_info_vm(vm_id)
  • reap_expired()
  • run_in_vm(...)

Behavioral defaults:

  • Pyro.create_vm(...) and Pyro.run_in_vm(...) default to vcpu_count=1 and mem_mib=1024.
  • Pyro.create_workspace(...) defaults to vcpu_count=1 and mem_mib=1024.
  • allow_host_compat defaults to False on create_vm(...) and run_in_vm(...).
  • allow_host_compat defaults to False on create_workspace(...).
  • Pyro.create_workspace(..., seed_path=...) seeds /workspace from a host directory or a local .tar / .tar.gz / .tgz archive before the workspace is returned.
  • Pyro.create_workspace(..., secrets=...) persists guest-only UTF-8 secrets outside /workspace.
  • Pyro.push_workspace_sync(...) imports later host-side directory or archive content into a started workspace.
  • Pyro.export_workspace(...) exports one file or directory from /workspace to an explicit host path.
  • Pyro.diff_workspace(...) compares the current /workspace tree to the immutable create-time baseline.
  • Pyro.create_snapshot(...) captures one named /workspace checkpoint.
  • Pyro.list_snapshots(...) lists the implicit baseline plus any named snapshots.
  • Pyro.delete_snapshot(...) deletes one named snapshot while leaving baseline intact.
  • Pyro.reset_workspace(...) recreates the full sandbox from baseline or one named snapshot and clears command, shell, and service history.
  • Pyro.start_service(..., secret_env=...) maps persisted workspace secrets into that service process as environment variables for that start call only.
  • Pyro.start_service(...) starts one named long-running process in a started workspace and waits for its typed readiness probe when configured.
  • Pyro.list_services(...), Pyro.status_service(...), Pyro.logs_service(...), and Pyro.stop_service(...) manage those persisted workspace services.
  • Pyro.exec_vm(...) runs one command and auto-cleans that VM after the exec completes.
  • Pyro.exec_workspace(..., secret_env=...) maps persisted workspace secrets into that exec call as environment variables for that call only.
  • Pyro.exec_workspace(...) runs one command in the persistent workspace and leaves it alive.
  • Pyro.open_shell(..., secret_env=...) maps persisted workspace secrets into the shell environment when that shell opens.
  • Pyro.open_shell(...) opens a persistent PTY shell attached to one started workspace.
  • Pyro.read_shell(...) reads merged text output from that shell by cursor.
  • Pyro.write_shell(...), Pyro.signal_shell(...), and Pyro.close_shell(...) operate on that persistent shell session.

MCP Contract

Primary tool:

  • vm_run

Advanced lifecycle tools:

  • vm_list_environments
  • vm_create
  • vm_start
  • vm_exec
  • vm_stop
  • vm_delete
  • vm_status
  • vm_network_info
  • vm_reap_expired

Persistent workspace tools:

  • workspace_create
  • workspace_sync_push
  • workspace_exec
  • workspace_export
  • workspace_diff
  • snapshot_create
  • snapshot_list
  • snapshot_delete
  • workspace_reset
  • service_start
  • service_list
  • service_status
  • service_logs
  • service_stop
  • shell_open
  • shell_read
  • shell_write
  • shell_signal
  • shell_close
  • workspace_status
  • workspace_logs
  • workspace_delete

Behavioral defaults:

  • vm_run and vm_create default to vcpu_count=1 and mem_mib=1024.
  • workspace_create defaults to vcpu_count=1 and mem_mib=1024.
  • vm_run and vm_create expose allow_host_compat, which defaults to false.
  • workspace_create exposes allow_host_compat, which defaults to false.
  • workspace_create accepts optional seed_path and seeds /workspace from a host directory or a local .tar / .tar.gz / .tgz archive before the workspace is returned.
  • workspace_create accepts optional secrets and persists guest-only UTF-8 secret material outside /workspace.
  • workspace_sync_push imports later host-side directory or archive content into a started workspace, with an optional dest under /workspace.
  • workspace_export exports one file or directory from /workspace to an explicit host path.
  • workspace_diff compares the current /workspace tree to the immutable create-time baseline.
  • snapshot_create, snapshot_list, and snapshot_delete manage explicit named snapshots in addition to the implicit baseline.
  • workspace_reset recreates the full sandbox and restores /workspace from baseline or one named snapshot.
  • service_start, service_list, service_status, service_logs, and service_stop manage persistent named services inside a started workspace.
  • vm_exec runs one command and auto-cleans that VM after the exec completes.
  • workspace_exec accepts optional secret_env mappings for one exec call and leaves the workspace alive.
  • service_start accepts optional secret_env mappings for one service start call.
  • shell_open accepts optional secret_env mappings for the opened shell session.
  • shell_open, shell_read, shell_write, shell_signal, and shell_close manage persistent PTY shells inside a started workspace.

Versioning Rule

  • pyro-mcp uses SemVer.
  • Environment names are stable identifiers in the shipped catalog.
  • Changing a public command name, public flag, public method name, public MCP tool name, or required request field is a breaking change.