pyro-mcp/docs/public-contract.md
Thales Maciel 407c805ce2 Clarify workspace-core as the chat-host onramp
Make the recommended MCP profile visible from the first help and docs pass without changing 3.x behavior.

Rework  help, top-level docs, public-contract wording, and shipped MCP/OpenAI examples so  is the recommended first profile while  stays the compatibility default for full-surface hosts.

Bump the package and catalog to 3.8.0, mark the roadmap milestone done, and add regression coverage for the new MCP help and docs alignment. Validation included uv lock, targeted profile/help tests, make check, make dist-check, and a real guest-backed  server smoke.
2026-03-13 11:23:51 -03:00

22 KiB

Public Contract

This document defines the stable public interface for pyro-mcp 3.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

Stable product framing:

  • pyro run is the stable one-shot entrypoint.
  • pyro workspace ... is the stable persistent workspace contract.

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 list
  • pyro workspace sync push
  • pyro workspace stop
  • pyro workspace start
  • pyro workspace exec
  • pyro workspace file list
  • pyro workspace file read
  • pyro workspace file write
  • pyro workspace export
  • pyro workspace patch apply
  • pyro workspace disk export
  • pyro workspace disk list
  • pyro workspace disk read
  • 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 update
  • 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 --id-only prints only the new workspace_id plus a trailing newline.
  • pyro workspace create --name NAME --label KEY=VALUE attaches human-oriented discovery metadata without changing the stable workspace_id.
  • pyro workspace create --network-policy {off,egress,egress+published-ports} controls workspace guest networking and whether services may publish localhost ports.
  • pyro mcp serve --profile {vm-run,workspace-core,workspace-full} narrows the model-facing MCP surface without changing runtime behavior; workspace-core is the recommended first profile for most chat hosts.
  • pyro workspace create --secret NAME=VALUE and --secret-file NAME=PATH persist guest-only UTF-8 secrets outside /workspace.
  • pyro workspace list returns persisted workspaces sorted by most recent last_activity_at.
  • 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 stop WORKSPACE_ID stops one persistent workspace without deleting its /workspace, snapshots, or command history.
  • pyro workspace start WORKSPACE_ID restarts one stopped workspace without resetting /workspace.
  • pyro workspace file list WORKSPACE_ID [PATH] [--recursive] returns metadata for one live path under /workspace.
  • pyro workspace file read WORKSPACE_ID PATH [--max-bytes N] reads one regular text file under /workspace.
  • pyro workspace file write WORKSPACE_ID PATH --text TEXT and --text-file PATH create or replace one regular text file under /workspace, creating missing parent directories automatically.
  • pyro workspace export WORKSPACE_ID PATH --output HOST_PATH exports one file or directory from /workspace back to the host.
  • pyro workspace disk export WORKSPACE_ID --output HOST_PATH copies the stopped guest-backed workspace rootfs as raw ext4 to the host.
  • pyro workspace disk list WORKSPACE_ID [PATH] [--recursive] inspects a stopped guest-backed workspace rootfs offline without booting the guest.
  • pyro workspace disk read WORKSPACE_ID PATH [--max-bytes N] reads one regular file from a stopped guest-backed workspace rootfs offline.
  • pyro workspace disk * requires state=stopped and a guest-backed workspace; it fails on host_compat.
  • 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 service start --publish GUEST_PORT or --publish HOST_PORT:GUEST_PORT publishes one guest TCP port to 127.0.0.1 on the host.
  • 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 patch apply WORKSPACE_ID --patch TEXT and --patch-file PATH apply one unified text patch with add/modify/delete operations under /workspace.
  • pyro workspace shell open --id-only prints only the new shell_id plus a trailing newline.
  • 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 shell read --plain --wait-for-idle-ms 300 is the recommended chat-facing read mode; raw shell reads remain available without --plain.
  • pyro workspace logs returns persisted command history for that workspace until pyro workspace delete.
  • pyro workspace update changes only discovery metadata such as name and key/value labels.
  • Workspace create/status results expose workspace_seed metadata describing how /workspace was initialized.
  • Workspace create/status/reset/update results expose name, labels, and last_activity_at.
  • Workspace create/status/reset results expose network_policy.
  • 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.
  • pyro workspace list returns one summary row per persisted workspace with workspace_id, name, labels, environment, state, created_at, last_activity_at, expires_at, command_count, service_count, and running_service_count.
  • pyro workspace service start, pyro workspace service list, and pyro workspace service status expose published-port metadata when present.

Python SDK Contract

Primary facade:

  • Pyro

Supported public entrypoints:

  • create_server(profile="workspace-full")
  • Pyro.create_server(profile="workspace-full")
  • Pyro.list_environments()
  • Pyro.pull_environment(environment)
  • Pyro.inspect_environment(environment)
  • Pyro.prune_environments()
  • Pyro.create_vm(...)
  • Pyro.create_workspace(..., name=None, labels=None, network_policy="off", secrets=None)
  • Pyro.list_workspaces()
  • Pyro.push_workspace_sync(workspace_id, source_path, *, dest="/workspace")
  • Pyro.stop_workspace(workspace_id)
  • Pyro.start_workspace(workspace_id)
  • Pyro.list_workspace_files(workspace_id, path="/workspace", recursive=False)
  • Pyro.read_workspace_file(workspace_id, path, *, max_bytes=65536)
  • Pyro.write_workspace_file(workspace_id, path, *, text)
  • Pyro.export_workspace(workspace_id, path, *, output_path)
  • Pyro.apply_workspace_patch(workspace_id, *, patch)
  • Pyro.export_workspace_disk(workspace_id, *, output_path)
  • Pyro.list_workspace_disk(workspace_id, path="/workspace", recursive=False)
  • Pyro.read_workspace_disk(workspace_id, path, *, max_bytes=65536)
  • 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, published_ports=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, plain=False, wait_for_idle_ms=None)
  • 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.update_workspace(workspace_id, *, name=None, clear_name=False, labels=None, clear_labels=None)
  • Pyro.logs_workspace(workspace_id)
  • Pyro.network_info_vm(vm_id)
  • Pyro.reap_expired()
  • Pyro.run_in_vm(...)

Stable public method names:

  • create_server(profile="workspace-full")
  • list_environments()
  • pull_environment(environment)
  • inspect_environment(environment)
  • prune_environments()
  • create_vm(...)
  • create_workspace(..., name=None, labels=None, network_policy="off", secrets=None)
  • list_workspaces()
  • push_workspace_sync(workspace_id, source_path, *, dest="/workspace")
  • stop_workspace(workspace_id)
  • start_workspace(workspace_id)
  • list_workspace_files(workspace_id, path="/workspace", recursive=False)
  • read_workspace_file(workspace_id, path, *, max_bytes=65536)
  • write_workspace_file(workspace_id, path, *, text)
  • export_workspace(workspace_id, path, *, output_path)
  • apply_workspace_patch(workspace_id, *, patch)
  • export_workspace_disk(workspace_id, *, output_path)
  • list_workspace_disk(workspace_id, path="/workspace", recursive=False)
  • read_workspace_disk(workspace_id, path, *, max_bytes=65536)
  • 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, published_ports=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, plain=False, wait_for_idle_ms=None)
  • 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)
  • update_workspace(workspace_id, *, name=None, clear_name=False, labels=None, clear_labels=None)
  • 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(..., name=..., labels=...) attaches human-oriented discovery metadata without changing the stable workspace_id.
  • Pyro.create_workspace(..., network_policy="off"|"egress"|"egress+published-ports") controls workspace guest networking and whether services may publish host ports.
  • Pyro.create_workspace(..., secrets=...) persists guest-only UTF-8 secrets outside /workspace.
  • Pyro.list_workspaces() returns persisted workspace summaries sorted by most recent last_activity_at.
  • Pyro.push_workspace_sync(...) imports later host-side directory or archive content into a started workspace.
  • Pyro.stop_workspace(...) stops one persistent workspace without deleting its /workspace, snapshots, or command history.
  • Pyro.start_workspace(...) restarts one stopped workspace without resetting /workspace.
  • Pyro.list_workspace_files(...), Pyro.read_workspace_file(...), and Pyro.write_workspace_file(...) provide structured live /workspace inspection and text edits without shell quoting.
  • Pyro.export_workspace(...) exports one file or directory from /workspace to an explicit host path.
  • Pyro.apply_workspace_patch(...) applies unified text patches for add/modify/delete operations under /workspace.
  • Pyro.export_workspace_disk(...) copies the stopped guest-backed workspace rootfs as raw ext4 to an explicit host path.
  • Pyro.list_workspace_disk(...) inspects a stopped guest-backed workspace rootfs offline without booting the guest.
  • Pyro.read_workspace_disk(...) reads one regular file from a stopped guest-backed workspace rootfs offline.
  • stopped-workspace disk helpers require state=stopped and a guest-backed workspace; they fail on host_compat.
  • 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.start_service(..., published_ports=[...]) publishes one or more guest TCP ports to 127.0.0.1 on the host when the workspace network policy is egress+published-ports.
  • 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, with optional plain rendering and idle batching for chat-facing consumers.
  • Pyro.write_shell(...), Pyro.signal_shell(...), and Pyro.close_shell(...) operate on that persistent shell session.
  • Pyro.update_workspace(...) changes only discovery metadata such as name and key/value labels.

MCP Contract

Stable MCP profiles:

  • vm-run: exposes only vm_run
  • workspace-core: exposes vm_run, workspace_create, workspace_list, workspace_update, workspace_status, workspace_sync_push, workspace_exec, workspace_logs, workspace_file_list, workspace_file_read, workspace_file_write, workspace_patch_apply, workspace_diff, workspace_export, workspace_reset, and workspace_delete
  • workspace-full: exposes the complete stable MCP surface below

Behavioral defaults:

  • pyro mcp serve and create_server() default to workspace-full for 3.x compatibility.
  • workspace-core is the recommended first profile for most new chat-host integrations.
  • create_server(profile="workspace-core") and Pyro.create_server(profile="workspace-core") are the recommended entrypoints for most new chat-host integrations.
  • workspace-core narrows workspace_create by omitting network_policy and secrets.
  • workspace-core narrows workspace_exec by omitting secret_env.

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_list
  • workspace_sync_push
  • workspace_stop
  • workspace_start
  • workspace_exec
  • workspace_file_list
  • workspace_file_read
  • workspace_file_write
  • workspace_export
  • workspace_patch_apply
  • workspace_disk_export
  • workspace_disk_list
  • workspace_disk_read
  • 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_update
  • 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 name and labels metadata for human discovery without changing the stable workspace_id.
  • workspace_create accepts network_policy with off, egress, or egress+published-ports to control workspace guest networking and service port publication.
  • workspace_create accepts optional secrets and persists guest-only UTF-8 secret material outside /workspace.
  • workspace_list returns persisted workspace summaries sorted by most recent last_activity_at.
  • workspace_sync_push imports later host-side directory or archive content into a started workspace, with an optional dest under /workspace.
  • workspace_stop stops one persistent workspace without deleting its /workspace, snapshots, or command history.
  • workspace_start restarts one stopped workspace without resetting /workspace.
  • workspace_file_list, workspace_file_read, and workspace_file_write provide structured live /workspace inspection and text edits without shell quoting.
  • workspace_export exports one file or directory from /workspace to an explicit host path.
  • workspace_patch_apply applies unified text patches for add/modify/delete operations under /workspace.
  • workspace_disk_export copies the stopped guest-backed workspace rootfs as raw ext4 to an explicit host path.
  • workspace_disk_list inspects a stopped guest-backed workspace rootfs offline without booting the guest.
  • workspace_disk_read reads one regular file from a stopped guest-backed workspace rootfs offline.
  • stopped-workspace disk tools require state=stopped and a guest-backed workspace; they fail on host_compat.
  • 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.
  • service_start accepts optional published_ports to expose guest TCP ports on 127.0.0.1 when the workspace network policy is egress+published-ports.
  • 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.
  • workspace_update changes only discovery metadata such as name and key/value labels.
  • 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.