Command Palette

Search for a command to run...

UnylyUnyly
Browse all

Vibeos Mcp

FreeMaintained

Drive a vibeOS desktop from your own MCP client (Claude Code, Cursor, Codex).

GitHubEmbed

About

Drive a vibeOS desktop from your own MCP client (Claude Code, Cursor, Codex).

README

Drive a vibeOS desktop from your own MCP client — Claude Code, Cursor, Codex — instead of pasting an API key into the browser. vibeOS supplies the tools and the machine; your agent supplies the model.

claude mcp add vibeos -- npx vibeos-mcp

That is the whole install. The first time your agent needs the desktop it answers with a link — https://vibeos.sh/app#pair=… — open it, read the warning, accept, and the desktop is paired: its tools appear in the agent without a restart. The token behind the link is minted on your machine and remembered in ~/.vibeos-mcp/token.json for seven days (the desktop remembers it for the same seven — reloads and closed tabs keep the pairing); the token rides the link's fragment, so it stays out of the HTTP request — access logs, proxies, Referer never see it. It is still sent, once, in the pairing hello over the websocket to whichever relay is selected, so that relay's operator sees it (vibeos.sh on the default relay; you, on a self-hosted one). npx vibeos-mcp forget drops it. Starting from the desktop instead — Settings › Capabilities › Pair — still works: paste the command it shows, which carries --token. Forget this agent in the desktop ends a pairing at once.

Whoever opens the link hands their desktop to your agent, root included, so the warning is on the page before anything dials. Clients that do not show a server's instructions get a single pair_desktop tool that returns the link until a desktop is paired.

Why a relay exists

An MCP client spawns a subprocess or POSTs to an endpoint. A browser tab can do neither — it cannot listen, only dial out. So both ends dial the same relay and it pairs them by token and copies frames, parsing nothing beyond the first frame. (An unconnected socket still holds a pairing slot and can ping; two sockets that present the same token pair with each other, so a token is a shared secret, not a name — it reaches no desktop but the one whose tab holds it.) The default relay is wss://2yetm9bvy2.execute-api.us-east-1.amazonaws.com/prod (API Gateway + DynamoDB: pairing is durable, so it does not matter which server each side lands on), with wss://vibeos.sh/api/mcp/relay as fallback. The Capabilities pane's command carries --relay <url> when the tab is on a non-default one.

Security

The token is root on the desktop. The tool set includes edit_file on system/os.js and vm_exec, so anything holding it can rewrite the OS and run commands in the VM. It is sent as the first frame over the websocket, never in a URL, because URLs reach access logs, proxies and Referer headers — the websocket reaches only the relay operator, who sees it either way.

The relay sees the token and every tool call in plaintext. Assume the operator of the relay you select (vibeos.sh by default) can read what your agent does on your desktop, and pick a self-hosted relay if that is not acceptable.

Frame contract

Between the tab and this package. The relay does not interpret any of it.

Direction Frame Meaning
both → relay {"hello":"tab"|"agent","token":"<64 hex>"} first frame, pairs the socket
agent → tab {"want":"tools","agent":"<client name>","sampling":bool,"pairing":bool} sent on every (re)connect, and again after MCP initialize once the client's name and capabilities are known; sampling says whether the client's model can power apps; pairing that the package minted its token and no desktop has taken the link yet
tab → agent {"ask":N,"ai":{"prompt","images?":[{mime,base64}],"json?","system?"}} an app's api.ai call when the tab has no model of its own; answered via MCP sampling (sampling/createMessage) when the client supports it
agent → tab {"ask":N,"result":"…"} or {"ask":N,"error":"…"} the model's text, or why not (client cannot sample, 120 s deadline) — ask ids are the tab's, distinct from call ids
tab → agent {"tools":[{name,description,parameters}],"instructions":"…"} TOOL_SCHEMAS verbatim, plus the tab's map of the OS (~6 KB): passed to the client as the MCP server's instructions in the initialize result
agent → tab {"id":N,"tool":"name","input":{...}} a call
tab → agent {"id":N,"result":...} or {"id":N,"error":"..."} its answer; any {mime,base64} or {mimeType,data} object in a result, at any depth, reaches the MCP client as image content and {mime:"text/plain",text} as a text block, each replaced in the JSON by a marker; never a data: url in text
relay → either {"paired":true|false,"instance":"<id>"} the relay's answer to the hello: is the other side already there, and which relay function instance this is (tab and agent must land on the same one)
agent → relay {"ping":N} every 30 s; a relay that names its instance must answer within 10 s or this side redials
relay → agent {"pong":N,"instance":"<id>"} the relay's answer, never forwarded to the tab
relay → either {"bye":4001|4003,"reason":"…"} sent just before a normal close by a relay that cannot send custom close codes (API Gateway); means exactly what the close code would
relay → either {"error":"peer not connected","code":4002} the other end is gone
tab → relay {"revoke":true} byte-exact; the relay closes both ends 4003 and forgets the token
tab → relay {"ping":<ms>} every 30 s, answered by the relay the same way

The tab also sends {"tools":...} unsolicited when it connects. That is not enough on its own: this package usually pairs after the tab, and reconnects roughly every 800 s when the serverless function reaches its limit — so it asks on every connect and the tab must answer want.

A self-hosted desktop (the vibeOS container) runs its own relay: start the agent with --relay wss://<that host>/… and the pair link carries it as &relay=. A link with no &relay= means the public default; a container desktop refuses a link whose relay is not its own, naming the --relay to use, rather than silently pairing through infrastructure you do not run.

--relay (or VIBEOS_RELAY) takes a comma-separated list: a relay that cannot be reached at all falls through to the next; one that was open and dropped is redialed as is. A call whose frame exceeds 128 KB is refused with an error naming the size (API Gateway closes the sender above that); the tab does the same for results. An API Gateway {"message":"Internal server error",…} frame (a throttled lambda) fails in-flight calls loudly rather than vanishing.

Seeing the desktop

read_desktop returns the open windows (top first, with geometry), the dock and the machine state as structured text; {window} gives one window's body as text (password and hidden values never), {window, dom:true} its sanitised outerHTML, and {screen:"image"} the machine's screen (the VM's VGA canvas) as a JPEG at most 1024 wide and under about 110 KB for the relay, with the text console's rows alongside. The desktop's own windows are DOM, which the tab cannot rasterise without a large vendor library, so they come back as text, not pixels. list_themes, list_files and search_file over a directory or glob (in a worker, 3 s deadline) complete the picture; the chat log and machine snapshots under system/ are the person's and are not readable.

initialize waits up to 3.5 s (VIBEOS_INIT_WAIT_MS) for the tab's first tools frame so the instructions can ride the initialize result — MCP has no second chance to send them. A tab that pairs later gets them to the next client that connects; the current one works from the tool descriptions, and stderr says so once.

Failure behaviour

Calls fail; they never hang. An MCP client waiting forever is indistinguishable from one doing slow work, and the user cannot tell the difference.

  • Relay drops mid-call (the ~800 s cut): in-flight calls reject with a note that the desktop may still have run the tool. The socket redials in place.
  • The tab never answers (its main thread is busy — a catastrophic regex in search_file measured about 50 s): the call fails at a deadline, 120 s by default (VIBEOS_CALL_TIMEOUT_MS), or timeout_s + 30 s for vm_exec, with a note that the desktop may still finish it.
  • No tab paired: tools/list answers within 2 s with an empty list — Claude Code gives up on a slow list and shows the server as broken — and sends notifications/tools/list_changed the moment the tab's schemas arrive. A tools/call in the gap errors with the relay instance id, so it can be compared with the one the Capabilities pane shows.
  • The tab's socket dies with a call in flight: the relay tells this side 4002 at once (not on the next send), so the call fails with the same note.
  • A second vibeos-mcp on the same token (close code 4001): final for the first one. Stop one, or pair a new token.
  • The pairing outlives the tab. The token is remembered in that browser for seven days: reload_os, a hand reload or a closed tab only open a gap — calls in it fail with peer not connected — and a tab back on the same token answers again; this package reconnects on its own. A second tab of the same browser offers Take over here rather than dialing over the first, and the first is told. Forget this agent in the pane, or the expiry, ends it: a connected package reads revoked (4003); one that dials afterwards finds no tab.
  • Revoked in Settings (close code 4003): final. No redial; every later call and tools/list say the desktop revoked the token.

Development

node e2e.mjs   # real relay, fake tab, this package over real MCP stdio

from github.com/caffeinum/vibeos-mcp

Install Vibeos Mcp in Claude Desktop, Claude Code & Cursor

Recommended · one command, every IDE
unyly install vibeos-mcp

Installs into Claude Desktop, Claude Code, Cursor & VS Code — handles npx, uvx and build-from-source repos for you.

First time? Get the CLI: curl -fsSL https://unyly.org/install | sh

Or configure manually

Run in your terminal:

claude mcp add vibeos-mcp -- npx -y vibeos-mcp

Step-by-step: how to install Vibeos Mcp

FAQ

Is Vibeos Mcp MCP free?

Yes, Vibeos Mcp MCP is free — one-click install via Unyly at no cost.

Does Vibeos Mcp need an API key?

No, Vibeos Mcp runs without API keys or environment variables.

Is Vibeos Mcp hosted or self-hosted?

Self-hosted: the server runs locally on your machine via the install command above.

How do I install Vibeos Mcp in Claude Desktop, Claude Code or Cursor?

Open Vibeos Mcp on unyly.org, pick your client tab (Claude Desktop, Claude Code, Cursor) and press Install — the config is generated automatically, no JSON editing.

Related MCPs

Compare Vibeos Mcp with

Not sure what to pick?

Find your stack in 60 seconds

Author?

Embed badge for your README

Browse similar

All development MCPs