Skip to main content

Headless vs Editor-Hosted

The same MCP server runs in two hosts. Headless, vv-app mcp [project] is the whole program: no window, the session lives on the main thread. Editor-hosted, the agent works on the project the user has open, through a Unix socket that a small bridge process connects to the client's stdio.

mcp-hosts.png

Comparison

AspectHeadlessEditor-hosted
Startvv-app mcp [project]Settings › Integrations or --mcp; the client runs vv-app mcp --attach [--pid N]
Transportrmcp over stdio, on its own threadUnix socket, one rmcp service per connection on a tokio thread
Session ownerMain thread, run_headlessShared between the UI thread and the McpHost thread
Ends whenThe client disconnectsMCP is disabled or the window closes
Editor-only toolsRefusedget_state, screenshot_ui, set_active_timeline

Sharing the session with the UI

In the editor the session moves between two threads through a slot (Mutex + Condvar). At the start of each frame the UI checks it out, catches up with what the agent did (events, a replaced project, a timeline to show) and edits it. At the end of the frame it checks it back in, together with its own state: gesture, open dialog, playhead, selection. The host thread runs calls only while the session is in the slot. Calls are therefore answered even when the window is hidden and receives no frames.

Guards

SituationBehaviour
User mid-gesture (drag, slider, pointer down)Mutating calls are held and run after the gesture, so they never join the user's undo group
A project dialog is open (project switch, OTIO decision, forced relink)Mutating calls are refused with "retry once it is closed"
Unsaved changesnew_project and open_project are refused
Window not drawnscreenshot_ui times out after 10 s
Agent-started jobsTheir outcome does not move the user's view
save_projectWrites a clone, so the UI is not held while the file is written

Socket security

There is no network port. Sockets live in $XDG_RUNTIME_DIR/venturi (falling back to /tmp/venturi-$USER), a directory set to 0700, as mcp-<pid>.sock with mode 0600. Sockets left behind by crashed editors are detected (connect fails) and removed. With several editors running, --attach needs --pid.