{
  "markdown": "# ZynoHosting CLI and MCP server\n\n`@zyno-io/zynohosting` is the public command-line and local MCP client for ZynoHosting. It can:\n\n- list sites authorized for the current tenant credential;\n- inspect, download, upload, and delete individual files;\n- preview and apply complete manifest-driven deployments;\n- download a complete deployable snapshot or, with the extra permission, all user content;\n- discover, create, inspect, edit, embed, and configure published ZynoForms;\n- expose the same operations to agents through a local stdio MCP server.\n\nThe package requires Node.js 24.\n\nFull CLI and MCP documentation is available at [zyno-io.github.io/zynohosting-cli](https://zyno-io.github.io/zynohosting-cli/).\n\n## Install\n\n```bash\nnpm install --global @zyno-io/zynohosting\nzynohosting --help\n```\n\nIt installs two executables:\n\n- `zynohosting` — the human and CI command-line interface;\n- `zynohosting-mcp` — the local stdio MCP server.\n\nYou can also run commands without a global install:\n\n```bash\nnpx -y @zyno-io/zynohosting sites list\n```\n\n## Authenticate\n\nFor an interactive user:\n\n```bash\nzynohosting login --permission hosting.sitesRead\nzynohosting login \\\n  --name \"Claude MCP — work laptop\" \\\n  --permission hosting.sitesRead \\\n  --permission hosting.deploy \\\n  --permission forms.create \\\n  --permission forms.edit \\\n  --renewable\n```\n\nBrowser login creates a tenant-bound scoped CLI token. `hosting.sitesRead` is requested when no `--permission` is supplied; repeat the option to request the narrowest complete set for your workflow. Access tokens always expire after 60 minutes. `--renewable` stores the rotating renewal credential in the operating system credential store and lets long-running CLI/MCP processes refresh automatically. While MCP remains alive, it renews in the background even when no tools are being called; each request also checks freshness as a backstop. The renewal secret is never written to the JSON config file.\n\nRevoke the saved scoped grant and remove its local credentials with `zynohosting logout`.\n\nFor CI or another non-interactive environment, inject a tenant API key:\n\n```bash\nexport ZYNOHOSTING_API_KEY='...'\n```\n\nThe CLI also accepts `--environment production|alpha|dev` and `--api-url`. Credentials are resolved in this order:\n\n1. command options;\n2. environment variables;\n3. the saved login file.\n\nRelevant environment variables are:\n\n- `ZYNOHOSTING_API_KEY`\n- `ZYNOHOSTING_ACCESS_TOKEN`\n- `ZYNOHOSTING_TENANT_ID`\n- `ZYNOHOSTING_TOKEN_EXPIRES_AT`\n- `ZYNOHOSTING_API_URL`\n- `ZYNO_SUITE_API_URL`\n- `ZYNO_AUTH_API_URL`\n- `ZYNOHOSTING_ENVIRONMENT`\n- `ZYNOHOSTING_CONFIG`\n- `ZYNOHOSTING_LOGIN_URL`\n\n## Sites\n\n```bash\nzynohosting sites list\nzynohosting sites get example.com\nzynohosting sites get 11111111-1111-4111-8111-111111111111 --json\n```\n\nA site may be addressed by its UUID, primary hostname, vanity hostname, or authorized alias.\n\n## Individual files\n\nRemote paths are relative to the site document root. Absolute paths, `..`, control characters, backslashes, and symbolic-link traversal are rejected.\n\n```bash\nzynohosting files list example.com\nzynohosting files list example.com wp-content/themes --recursive\n\nzynohosting files get example.com index.html --output ./index.html\nzynohosting files put example.com ./index.html index.html\nzynohosting files rm example.com obsolete.html --yes\n```\n\nUse ETags to prevent overwriting a file that changed since it was inspected:\n\n```bash\nzynohosting files put example.com ./index.html index.html --etag '\"etag-from-list\"'\nzynohosting files rm example.com obsolete.html --etag '\"etag-from-list\"' --yes\n```\n\nUse `--create` to require that an uploaded path does not already exist.\n\n## Full deployment\n\n```bash\nzynohosting deploy example.com ./dist\nzynohosting deploy example.com ./dist --dry-run\nzynohosting deploy example.com ./dist --yes\n```\n\nDeployment is always planned before it is applied. The client and node agent:\n\n1. agree on protocol limits and mandatory ignores;\n2. inventory local and remote content;\n3. hash only same-size candidates;\n4. return the exact create, replace, and delete plan;\n5. upload only changed files;\n6. revalidate the remote snapshot before mutation;\n7. invalidate the site cache after a successful apply.\n\nThe mandatory deployment scope excludes platform-managed configuration, uploads, caches, logs, VCS data, and dependencies. Add project exclusions in `.zynohostingignore` or with `--ignore`.\n\nAn empty local deployment requires `--allow-empty` before it may delete the remote deployable scope.\n\n## Complete download\n\nThe default snapshot mirrors the deployable scope:\n\n```bash\nzynohosting download example.com ./site-copy\n```\n\nDownloading protected configuration and user-generated content requires the separate `hosting.downloadSensitive` permission:\n\n```bash\nzynohosting download example.com ./complete-copy --sensitive\n```\n\nThe destination must be new or empty. Archive bytes are extracted as the hosting node generates them; the CLI validates the transport completion, gzip stream, and tar entries before atomically installing the staged tree. Absolute paths, traversal, links, devices, and other unsupported entries are rejected.\n\n## Local MCP server\n\nThe MCP server is local stdio only. It does not open a port or provide a hosted/cloud MCP endpoint.\n\nFor a non-technical user, paste this into Codex or Claude Code:\n\n> Set up ZynoHosting MCP for this project if it's not already configured. See https://raw.githubusercontent.com/zyno-io/zynohosting-cli/main/docs/mcp/agent.md for details.\n\nThe agent configures only its own project file—`.mcp.json` for Claude Code or `.codex/config.toml` for Codex—without storing credentials. Restart the agent after it completes; MCP tools are not added to an already-running session. That prompt points at [install instructions written for the agent](./docs/mcp/agent.md); the matching [prompts for the user](https://zyno-io.github.io/zynohosting-cli/mcp/setup) cover signing in, publishing, and forms.\n\n`ZYNOHOSTING_MCP_ROOTS` is an optional local-computer allowlist for the MCP process. When it is unset, local-file tools can use any absolute path the MCP process user can access. When roots are configured, local file reads, writes, deploy sources, ignore files, and download destinations are constrained to them after canonical path resolution.\n\nDirect invocation:\n\n```bash\nzynohosting-mcp --root /absolute/path/to/project\n```\n\nThe package’s main binary also exposes the registry-friendly form:\n\n```bash\nnpx -y @zyno-io/zynohosting mcp --root /absolute/path/to/project\n```\n\nExample client configuration:\n\n```json\n{\n    \"mcpServers\": {\n        \"zynohosting\": {\n            \"command\": \"npx\",\n            \"args\": [\"-y\", \"@zyno-io/zynohosting\", \"mcp\"],\n            \"env\": {\n                \"ZYNOHOSTING_MCP_ROOTS\": \"/absolute/path/to/project\"\n            }\n        }\n    }\n}\n```\n\nOn macOS and Linux, multiple `ZYNOHOSTING_MCP_ROOTS` use `:` as the delimiter. Windows uses `;`. Repeated `--root` arguments are also supported.\n\nThe MCP tools are:\n\n- `login`\n- `list_sites`\n- `get_site`\n- `list_forms`\n- `get_form_integration`\n- `describe_form`\n- `create_basic_form`\n- `update_form`\n- `update_form_bot_protection`\n- `update_form_origins`\n- `list_files`\n- `get_file`\n- `put_file`\n- `delete_file`\n- `plan_deploy`\n- `apply_deploy`\n- `plan_download`\n- `apply_download`\n\nFull deploys and downloads intentionally use separate plan/apply calls. Plans are held only in the local MCP process, contain no exposed bearer token, expire with their short-lived access session, and cannot be applied after the server restarts.\n\nThe MCP can start without a saved login. The agent calls `login` to open the ZynoSuite browser sign-in flow and receives the one-time URL in its tool result; after the browser callback, it calls `login` with `action: \"status\"` to confirm the login. It must never infer a deployment domain from the project or select a similar authorized site; it asks when the project does not state the target domain. If the stated domain is unavailable in the current login context, it must not substitute another one and should offer `login` again to switch contexts.\n\n## Permissions\n\nThe tenant credential is limited by explicit Hosting and Forms permissions:\n\n| Permission                  | Capability                                                |\n| --------------------------- | --------------------------------------------------------- |\n| `hosting.sitesRead`         | List and inspect sites                                    |\n| `hosting.filesRead`         | List files and download individual files                  |\n| `hosting.filesWrite`        | Create and replace individual files                       |\n| `hosting.filesDelete`       | Delete individual files                                   |\n| `hosting.deploy`            | Plan and apply full deployments                           |\n| `hosting.download`          | Download the deployable snapshot                          |\n| `hosting.downloadSensitive` | Include protected and user-generated content              |\n| `hosting.analyticsRead`     | Read hosting analytics                                    |\n| `hosting.analyticsManage`   | Change analytics configuration                            |\n| `forms.create`              | Create and immediately publish a basic form               |\n| `forms.edit`                | Edit a form, its Cap protection, and allowed CORS origins |\n\nThe form discovery and integration tools use the same tenant credential against the ZynoSuite API. Adding origins from a hosting-site reference also requires `hosting.sitesRead`.\n\nTenant admins receive the normal administrative defaults. Non-admin credentials receive only the operations explicitly granted to them.\n\nThat table is the complete set. `zynohosting login --help` prints it, and the MCP `login` tool enumerates it in its schema, so an invented key such as `hosting.sitesWrite` is rejected locally—naming the closest valid key—before a browser opens. CLI-token requests cannot include `msp.login`, `msp.impersonate`, `core.changePassword`, or `core.manageFingerprints`. The browser also refuses unknown permissions and permissions the current user does not possess; it never partially grants a request.\n\nOnly one MCP browser flow runs at a time. Repeating `login` with the same request returns the same one-time URL (`\"reused\": true`); requesting different permissions cancels the in-flight flow and issues a new URL rather than handing back the earlier scope. `action: \"cancel\"` abandons a flow and closes its loopback listener.\n\n## JSON output\n\nMost CLI commands accept `--json`. Deploy emits newline-delimited progress, plan, and result events; list and file commands emit a single JSON document.\n\n## Public API and release process\n\nThe [public documentation site](https://zyno-io.github.io/zynohosting-cli/) covers CLI commands, MCP tools, configuration, permissions, and safety. The manager and node-agent contract is documented in [BACKEND_PLAN.md](./BACKEND_PLAN.md). Maintainer release setup and the tag-only mirror design are documented in [RELEASING.md](./RELEASING.md).\n",
  "bytes": 11119,
  "sha": "169ed4cd017e325b0db3b3cb326a25bc97e45fbb32938149bfb1d63643308d82",
  "repo_slug": "zyno-io/zynohosting-cli",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_zyno_io_zynohosting_30874f60/readme"
}