{"_id":"@descanto/vm-mcp","_rev":"6-c904f35a61878bc78e026311a733424f","name":"@descanto/vm-mcp","dist-tags":{"latest":"0.0.5"},"versions":{"0.0.1":{"name":"@descanto/vm-mcp","version":"0.0.1","keywords":["canto","descanto","cloud-desktop","computer-use","agent","vm","firecracker"],"author":{"name":"Descanto"},"license":"PolyForm-Noncommercial-1.0.0","_id":"@descanto/vm-mcp@0.0.1","maintainers":[{"name":"dylanvrbty","email":"ducitymp@gmail.com"}],"homepage":"https://docs.descanto.com/docs/canto","bugs":{"url":"https://github.com/Descanto/vm/issues"},"bin":{"descanto-vm-mcp":"dist/index.js"},"dist":{"shasum":"1d3f36b2b2dc65f55a08304e54cb30c66f90aae7","tarball":"https://registry.npmjs.org/@descanto/vm-mcp/-/vm-mcp-0.0.1.tgz","fileCount":5,"integrity":"sha512-s6funR7oizb4o3Mt7B7L4wXPRmaQm7XVJsdZMUwBO4IZSIlxhoWmsoC0FsOqlxL+00LLeiTEhD2Xs7xIVDUzFQ==","signatures":[{"sig":"MEUCIQCSlNklt+z6QOn8pakQhCZX8iGfXZ0VSqeDDlRUGcSjjgIgSiKHPtVY/VOLLfebXIGQ/TzJAJV4vmHQbI+sncgIRrU=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":173345},"type":"module","engines":{"node":">=18"},"gitHead":"92c37809732c9b1fc11c5cfe4fc12a33f94d1e34","scripts":{"dev":"tsup --watch","test":"vitest run","build":"tsup","start":"node dist/index.js","typecheck":"tsc --noEmit","test:watch":"vitest","prepublishOnly":"bun run build"},"_npmUser":{"name":"dylanvrbty","email":"ducitymp@gmail.com"},"repository":{"url":"git+https://github.com/Descanto/vm.git","type":"git","directory":"canto/mcp"},"_npmVersion":"11.6.2","description":"MCP stdio server exposing Canto cloud desktops to MCP-compatible AI clients","directories":{},"_nodeVersion":"25.2.1","dependencies":{"zod":"^4.0.0","@modelcontextprotocol/sdk":"^1.30.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.1","vitest":"^4.1.11","typescript":"^5.6.0","@types/node":"^26.2.0","@descanto/vm-sdk":"file:../sdk-typescript"},"_npmOperationalInternal":{"tmp":"tmp/vm-mcp_0.0.1_1787161010375_0.23110843705605322","host":"s3://npm-registry-packages-npm-production"},"deprecated":"Renamed to @descanto/mcp"},"0.0.2":{"name":"@descanto/vm-mcp","version":"0.0.2","keywords":["canto","descanto","cloud-desktop","computer-use","agent","vm","firecracker"],"author":{"name":"Descanto"},"license":"Elastic-2.0","_id":"@descanto/vm-mcp@0.0.2","maintainers":[{"name":"dylanvrbty","email":"ducitymp@gmail.com"}],"homepage":"https://docs.descanto.com/docs/canto","bugs":{"url":"https://github.com/Descanto/vm/issues"},"bin":{"descanto-vm-mcp":"dist/index.js"},"dist":{"shasum":"589c650fa995bc155bff78b2159bc8b7ad64bbda","tarball":"https://registry.npmjs.org/@descanto/vm-mcp/-/vm-mcp-0.0.2.tgz","fileCount":5,"integrity":"sha512-XUZVfYE78TVG+cEhK8nSfpk6ee4pf7MZ+gTrsOSneq2L5sdujIyx+dMhokS1G9bjd5wjCf22l8DaFzcWPWEgbA==","signatures":[{"sig":"MEYCIQCVlZVTpFqsIO7yFHeRdIepsLoiWV45JGVS7mMUzjA/4gIhANsqpDMm+wUVo4fezxBG+pzQLUvXPnFFbqmy1Sw8GUoX","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":168092},"type":"module","engines":{"node":">=18"},"gitHead":"c26affac9c214d447d7cecf61003d9116168ab11","scripts":{"dev":"tsup --watch","test":"vitest run","build":"tsup","start":"node dist/index.js","typecheck":"tsc --noEmit","test:watch":"vitest","prepublishOnly":"bun run build"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:5d5e770f-2389-4b82-8e8a-973d17447736"}},"repository":{"url":"git+https://github.com/Descanto/vm.git","type":"git","directory":"canto/mcp"},"_npmVersion":"12.0.2","description":"MCP stdio server exposing Canto cloud desktops to MCP-compatible AI clients","directories":{},"_nodeVersion":"22.23.2","dependencies":{"zod":"^4.0.0","@modelcontextprotocol/sdk":"^1.30.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.1","vitest":"^4.1.11","typescript":"^5.6.0","@types/node":"^26.2.0","@descanto/vm-sdk":"file:../sdk-typescript"},"_npmOperationalInternal":{"tmp":"tmp/vm-mcp_0.0.2_1787161548888_0.24790072137098895","host":"s3://npm-registry-packages-npm-production"},"deprecated":"Renamed to @descanto/mcp"},"0.0.3":{"name":"@descanto/vm-mcp","version":"0.0.3","keywords":["canto","descanto","cloud-desktop","computer-use","agent","vm","firecracker"],"author":{"name":"Descanto"},"license":"Elastic-2.0","_id":"@descanto/vm-mcp@0.0.3","maintainers":[{"name":"dylanvrbty","email":"ducitymp@gmail.com"}],"homepage":"https://docs.descanto.com/docs/canto","bugs":{"url":"https://github.com/Descanto/vm/issues"},"bin":{"descanto-vm-mcp":"dist/index.js"},"dist":{"shasum":"cbd86a4a705ce6f8ac937fb0ac7923838ca74c6a","tarball":"https://registry.npmjs.org/@descanto/vm-mcp/-/vm-mcp-0.0.3.tgz","fileCount":5,"integrity":"sha512-YTL1FHUHOw09Yd0/Xl7JOm1rdW9hMNMQFtkKqqg7cNtpjFofiFyjEgsIYrprPewec/QN6H9SwwS2aCkywutpDw==","signatures":[{"sig":"MEUCIQCsG6HBsNHFyfGeb87mz1rjI72aDeRQawYdqnGYKbWRSwIgeq1ZsnyNHsT7SXz5pcubOjZi48TkVKnQaRkA1zTQSdQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":169344},"type":"module","engines":{"node":">=18"},"gitHead":"282b15d38a6a624407e4b29b23dfefa0effa4a5d","scripts":{"dev":"tsup --watch","test":"vitest run","build":"tsup","start":"node dist/index.js","typecheck":"tsc --noEmit","test:watch":"vitest","prepublishOnly":"bun run build"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:5d5e770f-2389-4b82-8e8a-973d17447736"}},"repository":{"url":"git+https://github.com/Descanto/vm.git","type":"git","directory":"canto/mcp"},"_npmVersion":"12.0.2","description":"MCP stdio server exposing Canto cloud desktops to MCP-compatible AI clients","directories":{},"_nodeVersion":"22.23.2","dependencies":{"zod":"^4.0.0","@modelcontextprotocol/sdk":"^1.30.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.1","vitest":"^4.1.11","typescript":"^5.6.0","@types/node":"^26.2.0","@descanto/vm-sdk":"file:../sdk-typescript"},"_npmOperationalInternal":{"tmp":"tmp/vm-mcp_0.0.3_1787162073135_0.7681976235675301","host":"s3://npm-registry-packages-npm-production"},"deprecated":"Renamed to @descanto/mcp"},"0.0.4":{"name":"@descanto/vm-mcp","version":"0.0.4","keywords":["canto","descanto","cloud-desktop","computer-use","agent","vm","firecracker"],"author":{"name":"Descanto"},"license":"Elastic-2.0","_id":"@descanto/vm-mcp@0.0.4","maintainers":[{"name":"dylanvrbty","email":"ducitymp@gmail.com"}],"homepage":"https://docs.descanto.com/docs/canto","bugs":{"url":"https://github.com/Descanto/vm/issues"},"bin":{"descanto-vm-mcp":"dist/index.js"},"dist":{"shasum":"2ef01099c640ec03ab7dfd328a942ab7d1773b43","tarball":"https://registry.npmjs.org/@descanto/vm-mcp/-/vm-mcp-0.0.4.tgz","fileCount":5,"integrity":"sha512-eDc1IqVE4PmwWih+LL1jByMuGoHkknyumhreGw3AAlqT77Ni9iIHcvhITQ0gQ4pqkA4TBnOdMCAPlKgsMXqV5Q==","signatures":[{"sig":"MEYCIQCv7/ARIeYhFV6eQHJQLsCapMMWQ+w/2lq5jtutoxDwQwIhAIem6liM5EUCiffqO/Fd78P5HVAljLVqf1ATTMc5dafE","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":309038},"type":"module","engines":{"node":">=18"},"gitHead":"8a357880602a30626e70442e51bf268caade4bc1","scripts":{"dev":"tsup --watch","test":"vitest run","build":"tsup","start":"node dist/index.js","typecheck":"tsc --noEmit","test:watch":"vitest","prepublishOnly":"bun run build"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:5d5e770f-2389-4b82-8e8a-973d17447736"}},"repository":{"url":"git+https://github.com/Descanto/vm.git","type":"git","directory":"canto/mcp"},"_npmVersion":"12.0.2","description":"MCP stdio server exposing Canto cloud desktops to MCP-compatible AI clients","directories":{},"_nodeVersion":"22.23.2","dependencies":{"zod":"^4.0.0","@modelcontextprotocol/sdk":"^1.30.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.1","vitest":"^4.1.11","typescript":"^5.6.0","@types/node":"^26.2.0","@descanto/vm-sdk":"file:../sdk-typescript"},"_npmOperationalInternal":{"tmp":"tmp/vm-mcp_0.0.4_1787234550584_0.9600540642816608","host":"s3://npm-registry-packages-npm-production"},"deprecated":"Renamed to @descanto/mcp"},"0.0.5":{"name":"@descanto/vm-mcp","version":"0.0.5","keywords":["canto","descanto","cloud-desktop","computer-use","agent","vm","firecracker"],"author":{"name":"Descanto"},"license":"Elastic-2.0","_id":"@descanto/vm-mcp@0.0.5","maintainers":[{"name":"dylanvrbty","email":"ducitymp@gmail.com"}],"homepage":"https://docs.descanto.com/docs/canto","bugs":{"url":"https://github.com/Descanto/vm/issues"},"bin":{"descanto-vm-mcp":"dist/index.js"},"dist":{"shasum":"83f3e896f1d2523e7fb93a791c6190ce070a1d99","tarball":"https://registry.npmjs.org/@descanto/vm-mcp/-/vm-mcp-0.0.5.tgz","fileCount":5,"integrity":"sha512-V791IwN3rs0ZC2sUI6uowvQmLMu3lpFoPga1q5ThRw6/H+OO+s3eeNKDdJOKQVQnZLOaCDGEK+q0aBrgkpBojw==","signatures":[{"sig":"MEUCIQCiAyJI+JWivRQ7V6ESox1OgdBxIrEqP9vWyaejRIJr1QIgO50R0dXTqb7nRNo5FE6MW9zwCt0ElaWkNYWap35Wh58=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":309707},"type":"module","engines":{"node":">=18"},"gitHead":"ed25aca20f199ca66eb1643ac43280116b9f4611","scripts":{"dev":"tsup --watch","test":"vitest run","build":"tsup","start":"node dist/index.js","typecheck":"tsc --noEmit","test:watch":"vitest","prepublishOnly":"bun run build"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:5d5e770f-2389-4b82-8e8a-973d17447736"}},"repository":{"url":"git+https://github.com/Descanto/vm.git","type":"git","directory":"canto/mcp"},"_npmVersion":"12.0.2","description":"MCP stdio server exposing Canto cloud desktops to MCP-compatible AI clients","directories":{},"_nodeVersion":"22.23.2","dependencies":{"zod":"^4.0.0","@modelcontextprotocol/sdk":"^1.30.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.1","vitest":"^4.1.11","typescript":"^5.6.0","@types/node":"^26.2.0","@descanto/vm-sdk":"file:../sdk-typescript"},"_npmOperationalInternal":{"tmp":"tmp/vm-mcp_0.0.5_1787235498114_0.9672180965150576","host":"s3://npm-registry-packages-npm-production"},"deprecated":"Renamed to @descanto/mcp"}},"time":{"created":"2026-08-19T17:36:50.084Z","modified":"2026-08-21T20:09:32.758Z","0.0.1":"2026-08-19T17:36:50.577Z","0.0.2":"2026-08-19T17:45:49.046Z","0.0.3":"2026-08-19T17:54:33.282Z","0.0.4":"2026-08-20T14:02:30.777Z","0.0.5":"2026-08-20T14:18:18.262Z"},"bugs":{"url":"https://github.com/Descanto/vm/issues"},"author":{"name":"Descanto"},"license":"Elastic-2.0","homepage":"https://docs.descanto.com/docs/canto","keywords":["canto","descanto","cloud-desktop","computer-use","agent","vm","firecracker"],"repository":{"url":"git+https://github.com/Descanto/vm.git","type":"git","directory":"canto/mcp"},"description":"MCP stdio server exposing Canto cloud desktops to MCP-compatible AI clients","maintainers":[{"name":"dylanvrbty","email":"ducitymp@gmail.com"}],"readme":"# @descanto/vm-mcp\n\nMCP (Model Context Protocol) stdio server that gives AI clients — Claude Code,\nClaude Desktop, Cursor, and any other MCP-compatible tool — hands-on control of\n**[Canto](https://docs.descanto.com/docs/canto)** cloud desktops: create, wake,\nrun commands, read/write files, fork, and stream, all as MCP tools.\n\nShips as a single self-contained binary (`@descanto/vm-sdk` is bundled in), so\nthere's nothing to install — point your client at `npx -y @descanto/vm-mcp`.\n\n📖 **Full docs:** https://docs.descanto.com/docs/canto\n\n## Configuration\n\nThe server needs one environment variable:\n\n| Env var          | Required | Description |\n|------------------|----------|-------------|\n| `CANTO_API_KEY`  | yes      | `canto_sk_...` API key (or AuthKit JWT). The server exits immediately with a clear message if unset. |\n| `CANTO_BASE_URL` | no       | Canto API base URL. Defaults to the hosted API (`https://api.descanto.com`); set it only to point at a different endpoint (e.g. `http://127.0.0.1:8081` for a local controld). Older published versions defaulted to localhost, so the examples below set it explicitly — safe to keep either way. |\n\n### Claude Code\n\n```bash\nclaude mcp add canto --env CANTO_API_KEY=canto_sk_... --env CANTO_BASE_URL=https://api.descanto.com -- npx -y @descanto/vm-mcp\n```\n\n### Claude Desktop / Cursor / Antigravity\n\nThese use the same `mcpServers` shape — add it to `claude_desktop_config.json`\n(Claude Desktop), `.cursor/mcp.json` (Cursor), or `~/.gemini/config/mcp_config.json`\n(Antigravity, via **… → MCP Servers → View raw config**):\n\n```json\n{\n  \"mcpServers\": {\n    \"canto\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@descanto/vm-mcp\"],\n      \"env\": {\n        \"CANTO_API_KEY\": \"canto_sk_...\",\n        \"CANTO_BASE_URL\": \"https://api.descanto.com\"\n      }\n    }\n  }\n}\n```\n\n### Codex\n\n```bash\ncodex mcp add canto --env CANTO_API_KEY=canto_sk_... --env CANTO_BASE_URL=https://api.descanto.com -- npx -y @descanto/vm-mcp\n```\n\nor add it to `~/.codex/config.toml` by hand:\n\n```toml\n[mcp_servers.canto]\ncommand = \"npx\"\nargs = [\"-y\", \"@descanto/vm-mcp\"]\nenv = { CANTO_API_KEY = \"canto_sk_...\", CANTO_BASE_URL = \"https://api.descanto.com\" }\n```\n\n### GitHub Copilot (VS Code)\n\nAdd to `.vscode/mcp.json` — Copilot uses the top-level `servers` key and requires\n`\"type\": \"stdio\"`:\n\n```json\n{\n  \"servers\": {\n    \"canto\": {\n      \"type\": \"stdio\",\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@descanto/vm-mcp\"],\n      \"env\": {\n        \"CANTO_API_KEY\": \"canto_sk_...\",\n        \"CANTO_BASE_URL\": \"https://api.descanto.com\"\n      }\n    }\n  }\n}\n```\n\n### OpenCode\n\nAdd to `opencode.json` (project) or `~/.config/opencode/opencode.json` (global) —\nOpenCode nests servers under `mcp`, takes `command` as an array, and uses\n`environment` rather than `env`:\n\n```json\n{\n  \"$schema\": \"https://opencode.ai/config.json\",\n  \"mcp\": {\n    \"canto\": {\n      \"type\": \"local\",\n      \"command\": [\"npx\", \"-y\", \"@descanto/vm-mcp\"],\n      \"enabled\": true,\n      \"environment\": {\n        \"CANTO_API_KEY\": \"canto_sk_...\",\n        \"CANTO_BASE_URL\": \"https://api.descanto.com\"\n      }\n    }\n  }\n}\n```\n\n## Tools\n\n| Tool                | Description |\n|---------------------|-------------|\n| `list_desktops`     | List desktops, optionally filtered by `state`. Returns `{id, state, tier, billingMode, hostId}` per desktop. |\n| `create_desktop`    | Provision a desktop: `tier` (small/default/large), optional `billing_mode` (monthly/hourly), `idle_timeout_secs`, `env` (guest env vars → `/root/.canto/env` on first wake), `setup_script` (runs once on first wake). |\n| `wake_desktop`      | Wake a hibernated desktop (`desktop_id`, `wait` default true). Typically ~1–10s. |\n| `hibernate_desktop` | Hibernate an awake desktop to pause billing (`desktop_id`, `wait` default true). |\n| `destroy_desktop`   | Permanently destroy a desktop and its disk (`desktop_id`). Always waits; irreversible. |\n| `fork_desktop`      | Clone a **Hibernated** source into `count` (1–20) new, also-Hibernated desktops (`desktop_id`, `count`, optional `ephemeral`, `acknowledge_shared_state`: must be `true`). Returns `{desktopIds}`. |\n| `set_idle_timeout`  | Update how long an awake desktop sits idle before auto-hibernating (`desktop_id`, `idle_timeout_secs`; `0` disables). |\n| `exec`              | Run a shell command on an awake desktop (`desktop_id`, `command`, optional `timeout_secs`). Pass `detached: true` to spawn a long-running command and get `{processId}` back immediately. |\n| `get_process`       | Poll a detached process (`desktop_id`, `process_id`, optional `tail_bytes`). Returns `{processId, status, exitCode, stdoutTail, stderrTail}`; `status` is `running`/`exited`/`lost`. |\n| `read_file`         | Read a file (`desktop_id`, `path`). Text if valid UTF-8 under 50KB, else base64 (capped) or a size error. |\n| `write_file`        | Write a file (`desktop_id`, `path`, `content` or `content_base64`). Base64 is strictly validated before decoding. |\n| `get_stream_url`    | Get a short-lived signed stream URL (`desktop_id`, `claim`: view/control, default view). |\n| `expose_port`       | Publish a guest TCP port at a stable URL (`desktop_id`, `port`, optional `public`). Desktop must be awake. Returns `{url, token?, port, public}` — the `canto_pt_...` token is shown **once** and grants access to whatever the guest serves there. |\n| `list_ports`        | List a desktop's port exposures (`desktop_id`). Returns `{ports: [...]}` with `status` `bound`/`unbound`; never includes tokens. |\n| `stop_port`         | Stop an exposure by guest port number (`desktop_id`, `port`). The URL 404s afterwards. |\n| `usage`             | Awake-time usage and projected cost, per desktop and org-wide (`start_ms`/`end_ms`, default last 30 days). |\n| `screenshot`        | Capture the desktop's display as a PNG image block (`desktop_id`, optional `region` `{x,y,width,height}`, `scale_percent` 1–100). Results over 2MB are rejected with a hint to pass `scale_percent` — always scale down on large displays. |\n| `click`             | Click (`desktop_id`, optional `x`/`y` to move first, `button` left/right/middle, `double`). Returns the final `{cursor}` — as does every input tool below; there is no separate cursor-read tool. |\n| `move_mouse`        | Move the cursor to absolute coordinates (`desktop_id`, `x`, `y`). |\n| `drag`              | Drag from `from_x`/`from_y` (default: current cursor) to `to_x`/`to_y` (`desktop_id`, optional `button`). |\n| `scroll`            | Scroll the wheel at the current cursor position (`desktop_id`, `direction` up/down/left/right, `amount` 1–50). |\n| `type_text`         | Type into the focused element (`desktop_id`, `text` ≤ 8KB) — click the target first. |\n| `press_key`         | Press a key combo (`desktop_id`, `combo`: `+`-joined X keysyms, e.g. `ctrl+shift+t`, `Return`). |\n| `set_resolution`    | Resize the display (`desktop_id`, `width` 640–2560, `height` 480–1600). Returns the size actually applied; a 501 error means this desktop's image can't resize at runtime — use `screenshot`'s `scale_percent` instead. |\n\nComputer-use tools require an **awake** desktop (`wake_desktop` first). Input is\nnever gated by noVNC control sessions — a human viewer and these tools can\ninterleave. Input calls are not transactional: an error mid-action-batch means\nearlier effects already applied, so re-screenshot before retrying rather than\nblindly re-sending clicks.\n\n### Context protection\n\n`exec` stdout/stderr and `get_process` tails are each truncated at **50KB** in the\ntool *result* (never in the underlying API call), UTF-8-boundary-safe, with a\n`[truncated by canto-mcp]` marker — this protects the calling model's context\nwindow. For larger output, redirect to a file and fetch it with `read_file`, or\nre-run with `head`/`tail`. `read_file` returns text only when it's valid UTF-8 and\nsmall enough; otherwise base64, or a size error asking you to use `exec`.\n\n### Errors\n\nA failed Canto API call never crashes the server. Every tool catches the error and\nreturns an MCP tool-error (`isError: true`) whose message includes the API's HTTP\nstatus, title, and detail (and `operation_id` when relevant), so the model sees\nexactly what happened and can react.\n\n## License\n\n[Elastic License 2.0](./LICENSE). Free to use, copy, modify, and self-host — you\njust can't offer it to third parties as a hosted or managed service, or remove the\nlicense notices.\n","readmeFilename":"README.md"}