diff --git a/CHANGELOG.md b/CHANGELOG.md index 5c6ea7f..2b6ae71 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,17 @@ All notable user-visible changes to `pyro-mcp` are documented here. +## 3.11.0 + +- Added first-class host-specific MCP onramps for Claude Code, Codex, and + OpenCode so major chat-host users can copy one exact setup example instead of + translating the generic MCP config by hand. +- Reordered the main integration docs and examples so host-specific MCP setup + appears before the generic `mcpServers` fallback, while keeping + `workspace-core` as the recommended first profile everywhere user-facing. +- Kept Claude Desktop and Cursor as generic fallback examples instead of the + primary onramp path. + ## 3.10.0 - Aligned the five guest-backed workspace smoke scenarios with the recipe docs diff --git a/README.md b/README.md index 8e59c0a..cb7a3eb 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ It exposes the same runtime in three public forms: - Stable workspace walkthrough GIF: [docs/assets/workspace-first-run.gif](docs/assets/workspace-first-run.gif) - Terminal walkthrough GIF: [docs/assets/first-run.gif](docs/assets/first-run.gif) - PyPI package: [pypi.org/project/pyro-mcp](https://pypi.org/project/pyro-mcp/) -- What's new in 3.10.0: [CHANGELOG.md#3100](CHANGELOG.md#3100) +- What's new in 3.11.0: [CHANGELOG.md#3110](CHANGELOG.md#3110) - Host requirements: [docs/host-requirements.md](docs/host-requirements.md) - Integration targets: [docs/integrations.md](docs/integrations.md) - Public contract: [docs/public-contract.md](docs/public-contract.md) @@ -60,7 +60,7 @@ What success looks like: ```bash Platform: linux-x86_64 Runtime: PASS -Catalog version: 3.10.0 +Catalog version: 3.11.0 ... [pull] phase=install environment=debian:12 [pull] phase=ready environment=debian:12 @@ -156,19 +156,42 @@ policy, or disk tools. uvx --from pyro-mcp pyro mcp serve --profile workspace-core ``` -Minimal MCP config: +Copy-paste host-specific starts: + +- Claude Code: [examples/claude_code_mcp.md](examples/claude_code_mcp.md) +- Codex: [examples/codex_mcp.md](examples/codex_mcp.md) +- OpenCode: [examples/opencode_mcp_config.json](examples/opencode_mcp_config.json) +- Generic MCP config: [examples/mcp_client_config.md](examples/mcp_client_config.md) + +Claude Code: + +```bash +claude mcp add pyro -- uvx --from pyro-mcp pyro mcp serve --profile workspace-core +``` + +Codex: + +```bash +codex mcp add pyro -- uvx --from pyro-mcp pyro mcp serve --profile workspace-core +``` + +OpenCode `opencode.json` snippet: ```json { - "mcpServers": { + "mcp": { "pyro": { - "command": "uvx", - "args": ["--from", "pyro-mcp", "pyro", "mcp", "serve", "--profile", "workspace-core"] + "type": "local", + "enabled": true, + "command": ["uvx", "--from", "pyro-mcp", "pyro", "mcp", "serve", "--profile", "workspace-core"] } } } ``` +If `pyro-mcp` is already installed, replace the `uvx --from pyro-mcp pyro` +command with `pyro` in the same host-specific command or config shape. + Profile progression: - `workspace-core`: recommended first profile for normal persistent chat editing @@ -226,7 +249,7 @@ uvx --from pyro-mcp pyro env list Expected output: ```bash -Catalog version: 3.10.0 +Catalog version: 3.11.0 debian:12 [installed|not installed] Debian 12 environment with Git preinstalled for common agent workflows. debian:12-base [installed|not installed] Minimal Debian 12 environment for shell and core Unix tooling. debian:12-build [installed|not installed] Debian 12 environment with Git and common build tools preinstalled. @@ -343,7 +366,7 @@ machine consumption, use `--id-only` for only the identifier or `--json` for the workspace payload. Use `--seed-path` when you want the workspace to start from a host directory or a local `.tar` / `.tar.gz` / `.tgz` archive instead of an empty workspace. Use `pyro workspace sync push` when you want to import -later host-side changes into a started workspace. Sync is non-atomic in `3.10.0`; if it fails +later host-side changes into a started workspace. Sync is non-atomic in `3.11.0`; if it fails partway through, prefer `pyro workspace reset` to recover from `baseline` or one named snapshot. Use `pyro workspace diff` to compare the live `/workspace` tree to its immutable create-time baseline, and `pyro workspace export` to copy one changed file or directory back to the host. Use @@ -577,7 +600,10 @@ Recommended MCP tool profiles: - Python one-shot SDK example: [examples/python_run.py](examples/python_run.py) - Python lifecycle example: [examples/python_lifecycle.py](examples/python_lifecycle.py) - Python workspace example: [examples/python_workspace.py](examples/python_workspace.py) -- MCP client config example: [examples/mcp_client_config.md](examples/mcp_client_config.md) +- Claude Code MCP setup: [examples/claude_code_mcp.md](examples/claude_code_mcp.md) +- Codex MCP setup: [examples/codex_mcp.md](examples/codex_mcp.md) +- OpenCode MCP config: [examples/opencode_mcp_config.json](examples/opencode_mcp_config.json) +- Generic MCP client config: [examples/mcp_client_config.md](examples/mcp_client_config.md) - Claude Desktop MCP config: [examples/claude_desktop_mcp_config.json](examples/claude_desktop_mcp_config.json) - Cursor MCP config: [examples/cursor_mcp_config.json](examples/cursor_mcp_config.json) - OpenAI Responses API example: [examples/openai_responses_vm_run.py](examples/openai_responses_vm_run.py) diff --git a/docs/first-run.md b/docs/first-run.md index ea54aa7..40e5c3d 100644 --- a/docs/first-run.md +++ b/docs/first-run.md @@ -22,7 +22,7 @@ Networking: tun=yes ip_forward=yes ```bash $ uvx --from pyro-mcp pyro env list -Catalog version: 3.10.0 +Catalog version: 3.11.0 debian:12 [installed|not installed] Debian 12 environment with Git preinstalled for common agent workflows. debian:12-base [installed|not installed] Minimal Debian 12 environment for shell and core Unix tooling. debian:12-build [installed|not installed] Debian 12 environment with Git and common build tools preinstalled. @@ -116,12 +116,21 @@ $ uvx --from pyro-mcp pyro workspace service start WORKSPACE_ID app --secret-env $ uvx --from pyro-mcp pyro workspace create debian:12 --network-policy egress+published-ports $ uvx --from pyro-mcp pyro workspace service start WORKSPACE_ID app --ready-http http://127.0.0.1:8080/ --publish 18080:8080 -- ./start-app $ uvx --from pyro-mcp pyro mcp serve --profile workspace-core +$ claude mcp add pyro -- uvx --from pyro-mcp pyro mcp serve --profile workspace-core +$ codex mcp add pyro -- uvx --from pyro-mcp pyro mcp serve --profile workspace-core ``` For most chat hosts, `workspace-core` is the recommended first MCP profile. Move to `workspace-full` only when the host truly needs shells, services, snapshots, secrets, network policy, or disk tools. +Host-specific MCP starts: + +- Claude Code: [examples/claude_code_mcp.md](../examples/claude_code_mcp.md) +- Codex: [examples/codex_mcp.md](../examples/codex_mcp.md) +- OpenCode: [examples/opencode_mcp_config.json](../examples/opencode_mcp_config.json) +- Generic MCP config: [examples/mcp_client_config.md](../examples/mcp_client_config.md) + `pyro demo` proves the one-shot create/start/exec/delete VM lifecycle works end to end. Once that stable workspace flow works, continue with the five recipe docs in @@ -259,7 +268,7 @@ State: started Use `--seed-path` when the workspace should start from a host directory or a local `.tar` / `.tar.gz` / `.tgz` archive instead of an empty `/workspace`. Use `pyro workspace sync push` when you need to import later host-side changes into a started -workspace. Sync is non-atomic in `3.10.0`; if it fails partway through, prefer `pyro workspace reset` +workspace. Sync is non-atomic in `3.11.0`; if it fails partway through, prefer `pyro workspace reset` to recover from `baseline` or one named snapshot. Use `pyro workspace diff` to compare the current `/workspace` tree to its immutable create-time baseline, `pyro workspace snapshot *` to create named checkpoints, and `pyro workspace export` to copy one changed file or directory back to the diff --git a/docs/install.md b/docs/install.md index c00bb31..c7b2ccf 100644 --- a/docs/install.md +++ b/docs/install.md @@ -85,7 +85,7 @@ uvx --from pyro-mcp pyro env list Expected output: ```bash -Catalog version: 3.10.0 +Catalog version: 3.11.0 debian:12 [installed|not installed] Debian 12 environment with Git preinstalled for common agent workflows. debian:12-base [installed|not installed] Minimal Debian 12 environment for shell and core Unix tooling. debian:12-build [installed|not installed] Debian 12 environment with Git and common build tools preinstalled. @@ -243,6 +243,30 @@ For most chat-host integrations, start with `workspace-core`: uvx --from pyro-mcp pyro mcp serve --profile workspace-core ``` +Copy-paste host-specific starts: + +- Claude Code: [examples/claude_code_mcp.md](../examples/claude_code_mcp.md) +- Codex: [examples/codex_mcp.md](../examples/codex_mcp.md) +- OpenCode: [examples/opencode_mcp_config.json](../examples/opencode_mcp_config.json) +- Generic MCP config: [examples/mcp_client_config.md](../examples/mcp_client_config.md) + +Claude Code: + +```bash +claude mcp add pyro -- uvx --from pyro-mcp pyro mcp serve --profile workspace-core +``` + +Codex: + +```bash +codex mcp add pyro -- uvx --from pyro-mcp pyro mcp serve --profile workspace-core +``` + +OpenCode uses the `mcp`/`type: "local"` config shape shown in +[examples/opencode_mcp_config.json](../examples/opencode_mcp_config.json). If +`pyro-mcp` is already installed, replace the `uvx --from pyro-mcp pyro` +command with `pyro` in the same host-specific command or config shape. + Use profile progression like this: - `workspace-core`: recommended first profile for normal persistent chat editing @@ -296,7 +320,7 @@ the identifier programmatically, use `--id-only` for only the identifier or `--j workspace payload. Use `--seed-path` when the workspace should start from a host directory or a local `.tar` / `.tar.gz` / `.tgz` archive. Use `pyro workspace sync push` for later host-side changes to a started workspace. Sync -is non-atomic in `3.10.0`; if it fails partway through, prefer `pyro workspace reset` to recover +is non-atomic in `3.11.0`; if it fails partway through, prefer `pyro workspace reset` to recover from `baseline` or one named snapshot. Use `pyro workspace diff` to compare the current workspace tree to its immutable create-time baseline, `pyro workspace snapshot *` to capture named checkpoints, and `pyro workspace export` to copy one changed file or directory back to the host. Use diff --git a/docs/integrations.md b/docs/integrations.md index 47c5d6c..36b5bb3 100644 --- a/docs/integrations.md +++ b/docs/integrations.md @@ -63,12 +63,15 @@ Profile progression: - `pyro mcp serve --profile workspace-core` for the normal persistent chat loop - `pyro mcp serve --profile workspace-full` only when the model truly needs advanced workspace tools -Starter config: +Host-specific onramps: -- [examples/mcp_client_config.md](../examples/mcp_client_config.md) -- [examples/claude_desktop_mcp_config.json](../examples/claude_desktop_mcp_config.json) -- [examples/cursor_mcp_config.json](../examples/cursor_mcp_config.json) -- [docs/use-cases/README.md](use-cases/README.md) +- Claude Code: [examples/claude_code_mcp.md](../examples/claude_code_mcp.md) +- Codex: [examples/codex_mcp.md](../examples/codex_mcp.md) +- OpenCode: [examples/opencode_mcp_config.json](../examples/opencode_mcp_config.json) +- Generic MCP config: [examples/mcp_client_config.md](../examples/mcp_client_config.md) +- Claude Desktop fallback: [examples/claude_desktop_mcp_config.json](../examples/claude_desktop_mcp_config.json) +- Cursor fallback: [examples/cursor_mcp_config.json](../examples/cursor_mcp_config.json) +- Use-case recipes: [docs/use-cases/README.md](use-cases/README.md) ## Direct Python SDK diff --git a/docs/roadmap/llm-chat-ergonomics.md b/docs/roadmap/llm-chat-ergonomics.md index c028071..1c83344 100644 --- a/docs/roadmap/llm-chat-ergonomics.md +++ b/docs/roadmap/llm-chat-ergonomics.md @@ -6,7 +6,7 @@ goal: make the core agent-workspace use cases feel trivial from a chat-driven LLM interface. -Current baseline is `3.10.0`: +Current baseline is `3.11.0`: - the stable workspace contract exists across CLI, SDK, and MCP - one-shot `pyro run` still exists as the narrow entrypoint @@ -63,7 +63,7 @@ The remaining UX friction for a technically strong new user is now narrower: 7. [`3.8.0` Chat-Host Onramp And Recommended Defaults](llm-chat-ergonomics/3.8.0-chat-host-onramp-and-recommended-defaults.md) - Done 8. [`3.9.0` Content-Only Reads And Human Output Polish](llm-chat-ergonomics/3.9.0-content-only-reads-and-human-output-polish.md) - Done 9. [`3.10.0` Use-Case Smoke Trust And Recipe Fidelity](llm-chat-ergonomics/3.10.0-use-case-smoke-trust-and-recipe-fidelity.md) - Done -10. [`3.11.0` Host-Specific MCP Onramps](llm-chat-ergonomics/3.11.0-host-specific-mcp-onramps.md) +10. [`3.11.0` Host-Specific MCP Onramps](llm-chat-ergonomics/3.11.0-host-specific-mcp-onramps.md) - Done 11. [`4.0.0` Workspace-Core Default Profile](llm-chat-ergonomics/4.0.0-workspace-core-default-profile.md) Completed so far: @@ -90,12 +90,12 @@ Completed so far: transcript separation for files that do not end with a trailing newline. - `3.10.0` aligned the five guest-backed use-case smokes with their recipe docs and promoted `make smoke-use-cases` as the trustworthy verification path for the advertised workspace flows. +- `3.11.0` added exact host-specific MCP onramps for Claude Code, Codex, and OpenCode so new + chat-host users can copy one known-good setup example instead of translating the generic MCP + config manually. Planned next: -- `3.11.0` adds exact host-specific onramps for Claude, Codex, and OpenCode so - a new chat-host user can copy one known-good config or command instead of - translating the generic MCP example by hand. - `4.0.0` flips the default MCP profile from `workspace-full` to `workspace-core` so the no-flag server entrypoint finally matches the recommended docs path, while keeping explicit opt-in access to the full diff --git a/docs/roadmap/llm-chat-ergonomics/3.11.0-host-specific-mcp-onramps.md b/docs/roadmap/llm-chat-ergonomics/3.11.0-host-specific-mcp-onramps.md index db44805..9edc0fa 100644 --- a/docs/roadmap/llm-chat-ergonomics/3.11.0-host-specific-mcp-onramps.md +++ b/docs/roadmap/llm-chat-ergonomics/3.11.0-host-specific-mcp-onramps.md @@ -1,6 +1,6 @@ # `3.11.0` Host-Specific MCP Onramps -Status: Planned +Status: Done ## Goal diff --git a/examples/claude_code_mcp.md b/examples/claude_code_mcp.md new file mode 100644 index 0000000..6f7a18f --- /dev/null +++ b/examples/claude_code_mcp.md @@ -0,0 +1,20 @@ +# Claude Code MCP Setup + +Recommended profile: `workspace-core`. + +Package without install: + +```bash +claude mcp add pyro -- uvx --from pyro-mcp pyro mcp serve --profile workspace-core +claude mcp list +``` + +Already installed: + +```bash +claude mcp add pyro -- pyro mcp serve --profile workspace-core +claude mcp list +``` + +Move to `workspace-full` only when the chat truly needs shells, services, +snapshots, secrets, network policy, or disk tools. diff --git a/examples/codex_mcp.md b/examples/codex_mcp.md new file mode 100644 index 0000000..f9f2861 --- /dev/null +++ b/examples/codex_mcp.md @@ -0,0 +1,20 @@ +# Codex MCP Setup + +Recommended profile: `workspace-core`. + +Package without install: + +```bash +codex mcp add pyro -- uvx --from pyro-mcp pyro mcp serve --profile workspace-core +codex mcp list +``` + +Already installed: + +```bash +codex mcp add pyro -- pyro mcp serve --profile workspace-core +codex mcp list +``` + +Move to `workspace-full` only when the chat truly needs shells, services, +snapshots, secrets, network policy, or disk tools. diff --git a/examples/mcp_client_config.md b/examples/mcp_client_config.md index efd8af3..0fa7645 100644 --- a/examples/mcp_client_config.md +++ b/examples/mcp_client_config.md @@ -2,6 +2,15 @@ Recommended default for most chat hosts: `workspace-core`. +Use the host-specific examples first when they apply: + +- Claude Code: [examples/claude_code_mcp.md](claude_code_mcp.md) +- Codex: [examples/codex_mcp.md](codex_mcp.md) +- OpenCode: [examples/opencode_mcp_config.json](opencode_mcp_config.json) + +Use this generic config only when the host expects a plain `mcpServers` JSON +shape. + `pyro-mcp` is intended to be exposed to LLM clients through the public `pyro` CLI. Generic stdio MCP configuration using `uvx`: @@ -42,7 +51,7 @@ Primary profile for most agents: Use lifecycle tools only when the agent needs persistent VM state across multiple tool calls. -Concrete client-specific examples: +Other generic-client examples: - Claude Desktop: [examples/claude_desktop_mcp_config.json](claude_desktop_mcp_config.json) - Cursor: [examples/cursor_mcp_config.json](cursor_mcp_config.json) diff --git a/examples/opencode_mcp_config.json b/examples/opencode_mcp_config.json new file mode 100644 index 0000000..ce23db7 --- /dev/null +++ b/examples/opencode_mcp_config.json @@ -0,0 +1,9 @@ +{ + "mcp": { + "pyro": { + "type": "local", + "enabled": true, + "command": ["uvx", "--from", "pyro-mcp", "pyro", "mcp", "serve", "--profile", "workspace-core"] + } + } +} diff --git a/pyproject.toml b/pyproject.toml index bc66549..d6e3ded 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "pyro-mcp" -version = "3.10.0" +version = "3.11.0" description = "Stable Firecracker workspaces, one-shot sandboxes, and MCP tools for coding agents." readme = "README.md" license = { file = "LICENSE" } diff --git a/src/pyro_mcp/vm_environments.py b/src/pyro_mcp/vm_environments.py index a89e86e..dc2f67a 100644 --- a/src/pyro_mcp/vm_environments.py +++ b/src/pyro_mcp/vm_environments.py @@ -19,7 +19,7 @@ from typing import Any from pyro_mcp.runtime import DEFAULT_PLATFORM, RuntimePaths DEFAULT_ENVIRONMENT_VERSION = "1.0.0" -DEFAULT_CATALOG_VERSION = "3.10.0" +DEFAULT_CATALOG_VERSION = "3.11.0" OCI_MANIFEST_ACCEPT = ", ".join( ( "application/vnd.oci.image.index.v1+json", diff --git a/tests/test_cli.py b/tests/test_cli.py index 17d84b9..52807f2 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -2807,21 +2807,73 @@ def test_cli_workspace_shell_open_prints_id_only( def test_chat_host_docs_and_examples_recommend_workspace_core() -> None: readme = Path("README.md").read_text(encoding="utf-8") install = Path("docs/install.md").read_text(encoding="utf-8") + first_run = Path("docs/first-run.md").read_text(encoding="utf-8") integrations = Path("docs/integrations.md").read_text(encoding="utf-8") mcp_config = Path("examples/mcp_client_config.md").read_text(encoding="utf-8") + claude_code = Path("examples/claude_code_mcp.md").read_text(encoding="utf-8") + codex = Path("examples/codex_mcp.md").read_text(encoding="utf-8") + opencode = json.loads(Path("examples/opencode_mcp_config.json").read_text(encoding="utf-8")) + claude_cmd = ( + "claude mcp add pyro -- uvx --from pyro-mcp pyro mcp serve --profile workspace-core" + ) + codex_cmd = ( + "codex mcp add pyro -- uvx --from pyro-mcp pyro mcp serve --profile workspace-core" + ) assert "## Chat Host Quickstart" in readme assert "pyro mcp serve --profile workspace-core" in readme + assert claude_cmd in readme + assert codex_cmd in readme + assert "examples/opencode_mcp_config.json" in readme assert "recommended first profile for normal persistent chat editing" in readme assert "## Chat Host Quickstart" in install assert "pyro mcp serve --profile workspace-core" in install + assert claude_cmd in install + assert codex_cmd in install assert "advanced 3.x compatibility surface" in install + assert claude_cmd in first_run + assert codex_cmd in first_run + assert "Start most chat hosts with `workspace-core`." in integrations + assert "examples/claude_code_mcp.md" in integrations + assert "examples/codex_mcp.md" in integrations + assert "examples/opencode_mcp_config.json" in integrations assert '`Pyro.create_server(profile="workspace-core")` for most chat hosts' in integrations assert "Recommended default for most chat hosts: `workspace-core`." in mcp_config + assert "Use the host-specific examples first when they apply:" in mcp_config + assert "claude_code_mcp.md" in mcp_config + assert "codex_mcp.md" in mcp_config + assert "opencode_mcp_config.json" in mcp_config + + assert claude_cmd in claude_code + assert "claude mcp list" in claude_code + assert "workspace-full" in claude_code + + assert codex_cmd in codex + assert "codex mcp list" in codex + assert "workspace-full" in codex + + assert opencode == { + "mcp": { + "pyro": { + "type": "local", + "enabled": True, + "command": [ + "uvx", + "--from", + "pyro-mcp", + "pyro", + "mcp", + "serve", + "--profile", + "workspace-core", + ], + } + } + } def test_content_only_read_docs_are_aligned() -> None: diff --git a/uv.lock b/uv.lock index 6bdffd0..f993b93 100644 --- a/uv.lock +++ b/uv.lock @@ -715,7 +715,7 @@ crypto = [ [[package]] name = "pyro-mcp" -version = "3.10.0" +version = "3.11.0" source = { editable = "." } dependencies = [ { name = "mcp" },