Skip to main content
The Agent Panel, the mobile app, and any tool that pairs with a running session all speak one small WebSocket protocol to the orchestrator’s pairing listener. A third-party host is any client you build on that protocol — a Blender panel, a browser extension, a CLI, another editor — that attaches to a live desktop tab and drives its agent session. Same agent, same context, no second Claude Code process, nothing extra for the user to install.
This is the exact surface the mobile app is built on. If you can open a WebSocket and send JSON, you can build a host.

How it works

1

The desktop is already listening

When the Agent Panel is open, the orchestrator runs a token-gated pairing listener on the LAN (see Endpoints). Each open panel tab is a desktop tab with a stable tab_id and a live agent session.
2

Your host connects with the pairing token

Open a WebSocket to the pairing URL with the token in the query string. Without a valid token the connection is refused — pairing is the whole security boundary.
3

List and attach to a tab

Send list_tabs to discover the open desktop tabs, then attach_tab to mirror one. Your host now receives that tab’s activity (streamed) and can drive it.
4

Drive the shared session

Send user_message frames. While attached, the server routes them to the mirrored tab — so your message enters the same conversation the desktop agent is in. That’s what makes it “one agent, shared context” rather than a second session.

Endpoints

The pairing listener is derived from the bridge port (COMFYUI_MCP_BRIDGE_PORT, default 9180): Pairing URL:
  • The token is either pinned by the user via COMFYUI_MCP_PAIR_TOKEN (always-on pairing) or minted per session and handed out through the panel’s QR / pair flow. Your host obtains it the same way the mobile app does: the user pairs it once.
  • Bound to the LAN only. There is no built-in public exposure — if a user wants remote reach they front it with their own tunnel, and the token still gates it.

Message shapes

All frames are JSON objects with a type. Request/response frames carry a cid (correlation id) you choose, echoed back on the matching reply.

Inbound — host → orchestrator

Any other panel event you send while attached is likewise routed to the mirrored tab.

Outbound — orchestrator → host

Plus the mirrored tab’s live agent activity (streamed replies, status, cards), which your host renders.
attach_tab is authoritative — you cannot forge the target. The server overwrites any tab_id you put on an outbound frame with the tab you actually attached to. A host can only ever drive a tab it has explicitly attached to. This is deliberate; see below.

Security invariants — a host MUST preserve these

These are the guarantees that make pairing safe. Building a host that respects them is the whole contract; a host that tries to bypass them is exactly what the listener is designed to reject.
Preserving these isn’t a constraint on your host — it is the feature. They stop a client from hijacking a session it never paired to.
  1. Token gate. The listener refuses any connection without a valid pair token (verifyClient). Never build a flow that ships or embeds the token automatically — the user pairs, once, deliberately.
  2. Authoritative attach_tab stamping. The server, not the client, decides which tab your frames target. Don’t rely on client-supplied tab_id for routing; attach first, then send.
  3. Non-headless targets only. You may attach to a real desktop tab, never to another headless client (you can’t mirror another phone/host).
  4. One tab at a time. Attaching to B drops your subscription to A. Model a single active mirror per connection.
  5. Pinned socket kind. A connection’s kind (headless vs desktop) is fixed on its first hello; don’t try to flip it to escape the takeover guards.

Minimal reference client

Teach an LLM to build your adapter

Paste the prompt below into Claude, ChatGPT, or your coding agent to have it scaffold a host adapter for your platform. It carries the full protocol contract, so the model doesn’t have to guess.
Copy this into your LLM

Register your integration

Built something? Register it so it can be listed and so we can flag protocol changes to you before they ship:

Register a third-party host

Open the registration template on GitHub — name, platform, repo, and which protocol version you built against.
Stability: the frames above are what the mobile app ships on, but this is not yet a frozen, versioned contract — read the source (src/services/ui-bridge.ts) as the authority, and register your host so you’re notified when the shapes move.