{"_id":"@caffeinum/vibeos-mcp","_rev":"3-6adbe03f8dd4df46c17a5e5e6676ad26","name":"@caffeinum/vibeos-mcp","dist-tags":{"latest":"0.1.1"},"versions":{"0.1.0":{"name":"@caffeinum/vibeos-mcp","version":"0.1.0","keywords":["mcp","vibeos","claude-code","cursor"],"license":"MIT","_id":"@caffeinum/vibeos-mcp@0.1.0","maintainers":[{"name":"caffeinum","email":"theisease@gmail.com"}],"homepage":"https://vibeos.sh","bugs":{"url":"https://github.com/caffeinum/vibeos-mcp/issues"},"bin":{"vibeos-mcp":"index.mjs"},"dist":{"shasum":"9dece1dccf4eb4b02354979212dd8c73755efa19","tarball":"https://registry.npmjs.org/@caffeinum/vibeos-mcp/-/vibeos-mcp-0.1.0.tgz","fileCount":4,"integrity":"sha512-giDt56s8jaqavc51G2QJ83wug0PgjK0hb+XZWSnQcg5KqtPajo3gx7TyULHOJ1Ovm+5z867YN4Qqt/luhNaaMA==","signatures":[{"sig":"MEUCIQDZslUrRNRa5pcO6j4+XH6C5JzLUgnEcHG5Sn2SYhbZDQIgfd2+KjDkrrkZQROshCeq6/KBFtr+uyxL+JgbBN3wWoM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@caffeinum%2fvibeos-mcp@0.1.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":13563},"type":"module","engines":{"node":">=20"},"gitHead":"b76c01818e573d1925f229c325287c83b3adf763","scripts":{"test":"node e2e.mjs"},"_npmUser":{"name":"caffeinum","email":"theisease@gmail.com"},"repository":{"url":"git+https://github.com/caffeinum/vibeos-mcp.git","type":"git"},"_npmVersion":"11.19.0","description":"Drive a vibeOS desktop from your own MCP client (Claude Code, Cursor, Codex).","directories":{},"_nodeVersion":"24.20.0","dependencies":{"ws":"^8.18.0","@modelcontextprotocol/sdk":"^1.0.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/vibeos-mcp_0.1.0_1788558854746_0.5777703817736037","host":"s3://npm-registry-packages-npm-production"},"deprecated":"moved to vibeos-mcp"},"0.1.1":{"name":"@caffeinum/vibeos-mcp","version":"0.1.1","keywords":["mcp","vibeos","claude-code","cursor"],"license":"MIT","_id":"@caffeinum/vibeos-mcp@0.1.1","maintainers":[{"name":"caffeinum","email":"theisease@gmail.com"}],"homepage":"https://vibeos.sh","bugs":{"url":"https://github.com/caffeinum/vibeos-mcp/issues"},"bin":{"vibeos-mcp":"index.mjs"},"dist":{"shasum":"fcdc9ac6ae261e66194aa663181ec5e93ef66b5a","tarball":"https://registry.npmjs.org/@caffeinum/vibeos-mcp/-/vibeos-mcp-0.1.1.tgz","fileCount":4,"integrity":"sha512-sKJw5zd4IYC3CSw7bEWagqMe0kOB1aXxTkeW/zjCspM//kAJN7EfpvZNAhwSBKQchtrEdNTJ57le3jQXIjnSRw==","signatures":[{"sig":"MEUCIQCw62U3slSSGpLrxt1rKKmT2qFNKzQEJ0Ke+c5kmv1wSwIgCK2TcoQFGHNvmeD3/yK7KKtHdNMxwNXfBsjMOSl2xqM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEYCIQDjYfnqzpgJSsnLINVUKZ4IpIdK+ISO4Jdc7HYYjm4/mAIhALXzF9B2dsZRB8pD9yIQFeDOVnzypi34ej+o86T0jhzl","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@caffeinum%2fvibeos-mcp@0.1.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":13561},"type":"module","engines":{"node":">=20"},"gitHead":"8a94a4c88f8ffe3fb551a8f5fb5685bc4a99fbc8","scripts":{"test":"node e2e.mjs"},"_npmUser":{"name":"caffeinum","email":"theisease@gmail.com"},"repository":{"url":"git+https://github.com/caffeinum/vibeos-mcp.git","type":"git"},"_npmVersion":"11.19.0","description":"Drive a vibeOS desktop from your own MCP client (Claude Code, Cursor, Codex).","directories":{},"_nodeVersion":"24.20.0","dependencies":{"ws":"^8.18.0","@modelcontextprotocol/sdk":"^1.0.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/vibeos-mcp_0.1.1_1788559100534_0.09506614773450606","host":"s3://npm-registry-packages-npm-production"},"deprecated":"moved to vibeos-mcp"}},"time":{"created":"2026-09-04T21:54:14.592Z","modified":"2026-09-04T22:08:03.281Z","0.1.0":"2026-09-04T21:54:14.889Z","0.1.1":"2026-09-04T21:58:20.642Z"},"bugs":{"url":"https://github.com/caffeinum/vibeos-mcp/issues"},"license":"MIT","homepage":"https://vibeos.sh","keywords":["mcp","vibeos","claude-code","cursor"],"repository":{"url":"git+https://github.com/caffeinum/vibeos-mcp.git","type":"git"},"description":"Drive a vibeOS desktop from your own MCP client (Claude Code, Cursor, Codex).","maintainers":[{"name":"caffeinum","email":"theisease@gmail.com"}],"readme":"# vibeos-mcp\n\nDrive a [vibeOS](https://vibeos.sh/app) desktop from your own MCP client — Claude\nCode, Cursor, Codex — instead of pasting an API key into the browser. vibeOS\nsupplies the tools and the machine; your agent supplies the model.\n\n```sh\nclaude mcp add vibeos -- npx @caffeinum/vibeos-mcp --token <token>\n```\n\nGet the token from **Settings → Capabilities** in the desktop. It is one token\nper tab session: it dies when the tab closes, and *Revoke* kills it immediately.\n\n## Why a relay exists\n\nAn MCP client spawns a subprocess or POSTs to an endpoint. A browser tab can do\nneither — it cannot listen, only dial out. So both ends dial\n`wss://vibeos.sh/api/mcp/relay` and the server pairs them by token and copies\nframes. The relay parses nothing beyond the first frame.\n\n## Security\n\n**The token is root on the desktop.** The tool set includes `edit_file` on\n`system/os.js` and `vm_exec`, so anything holding it can rewrite the OS and run\ncommands in the VM. It is sent as the first frame and never in a URL, because\nURLs reach access logs, proxies and `Referer` headers.\n\nThe relay sees every tool call in plaintext. Assume the operator of vibeos.sh\ncan read what your agent does on your desktop.\n\n## Frame contract\n\nBetween the tab and this package. The relay does not interpret any of it.\n\n| Direction | Frame | Meaning |\n|---|---|---|\n| both → relay | `{\"hello\":\"tab\"\\|\"agent\",\"token\":\"<64 hex>\"}` | first frame, pairs the socket |\n| agent → tab | `{\"want\":\"tools\",\"agent\":\"<client name>\"}` | sent on every (re)connect, and again after MCP initialize once the client's name is known (empty before) |\n| tab → agent | `{\"tools\":[{name,description,parameters}]}` | `TOOL_SCHEMAS`, verbatim |\n| agent → tab | `{\"id\":N,\"tool\":\"name\",\"input\":{...}}` | a call |\n| tab → agent | `{\"id\":N,\"result\":...}` or `{\"id\":N,\"error\":\"...\"}` | its answer |\n| relay → either | `{\"paired\":true\\|false}` | the relay's answer to the hello: is the other side already there |\n| relay → either | `{\"error\":\"peer not connected\",\"code\":4002}` | the other end is gone |\n| tab → relay | `{\"revoke\":true}` | byte-exact; the relay closes both ends 4003 and forgets the token |\n| tab → agent | `{\"ping\":<ms>}` | every 30 s, so the relay's 4002 tells the tab the agent left; ignored here |\n\nThe tab also sends `{\"tools\":...}` unsolicited when it connects. That is not\nenough on its own: this package usually pairs *after* the tab, and reconnects\nroughly every 800 s when the serverless function reaches its limit — so it asks\non every connect and the tab must answer `want`.\n\n## Failure behaviour\n\nCalls fail; they never hang. An MCP client waiting forever is indistinguishable\nfrom one doing slow work, and the user cannot tell the difference.\n\n- Relay drops mid-call (the ~800 s cut): in-flight calls reject with a note that\n  the desktop may still have run the tool. The socket redials in place.\n- No tab paired: `tools/list` explains that no tab is connected rather than\n  reporting zero tools, which clients cache.\n- The tab's socket dies with a call in flight: the relay tells this side\n  `4002` at once (not on the next send), so the call fails with the same note.\n- A second `vibeos-mcp` on the same token (close code 4001): final for the\n  first one. Stop one, or pair a new token.\n- The tab closes or reloads — `reload_os` included, since the token lives in\n  the tab and dies with it: the tab sends the revoke on its way out, so this\n  reads as revoked (4003), not as a relay outage. Driving the desktop again\n  needs a new token from Settings > Capabilities.\n- Revoked in Settings (close code 4003): final. No redial; every later call\n  and `tools/list` say the desktop revoked the token.\n\n## Development\n\n```sh\nnode e2e.mjs   # real relay, fake tab, this package over real MCP stdio\n```\n","readmeFilename":"README.md"}