Studio Sessions & the MCP Authoring Loop

Beyond running layouts, CAR-TER supports authoring them live: push a layout to a paired device, see it render instantly, read back what's on screen, and iterate. The MCP server (carter-mcp) drives this loop, letting an LLM build and push layouts; you can also author programmatically with carterkit and push over the same mechanism. This is distinct from a data server (Anatomy of a CAR-TER Server); it's about editing the UI.

The MCP server is open source at github.com/Mariner10/carter-mcp (MIT). Clone it, install it, and point your AI client at it — the three steps below get you authoring on-device in a couple of minutes.

Get it running

1. Install

Requires Python 3.11+. Clone the repo and install its dependencies — a virtual environment is recommended so the server always finds them:

git clone https://github.com/Mariner10/carter-mcp.git
cd carter-mcp
python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt

That pulls carterkit (the layout-authoring engine), meshsocket (the transport), the mcp SDK, and qrcode.

2. Connect it to your AI client

carter-mcp speaks MCP over stdio under the server name carter; register server.py with your client, using the interpreter that has the dependencies (the venv Python above).

Claude Desktop — add to claude_desktop_config.json:

{
  "mcpServers": {
    "carter": {
      "command": "/absolute/path/to/carter-mcp/.venv/bin/python",
      "args": ["/absolute/path/to/carter-mcp/server.py"]
    }
  }
}

Claude Code — from the repo directory:

claude mcp add carter -- "$(pwd)/.venv/bin/python" "$(pwd)/server.py"

Restart the client and you should see the carter server and its tools. To smoke-test the server on its own, run python server.py (it serves MCP on stdio and waits).

3. Author your first layout

Ask your assistant something like "pair with my phone and build a two-gauge server dashboard." It will connect() (a zero-config local relay + a pairing QR — no account, no cloud), you scan the QR with CAR-TER on the same Wi-Fi to start a Studio Session, and it push_layout(...)s the panel — which renders on your device instantly and echoes back exactly what rendered. The full tool sequence is in A typical loop below.

How a Studio Session works

  1. The authoring client (the MCP) connects to a relay and shows a pairing QR (Connection & Pairing).
  2. The phone scans it and starts a Studio Session (role viewer/editor), rendering a pushed layout and re-rendering on every push.
  3. The client pushes layouts and reads device state over MeshSocket.

During a Studio Session the device arms read-back responders so the client isn't flying blind. They are routed-request handlers (answered via route_msg):

Verb Returns
get-current-layout The layout currently live (summary or full JSON)
get-control-state Current control values ({ id: value })
get-connection-status Connected?/phase/channel/role/which events it's listening on
apply-layout Applies a pushed layout and echoes exactly what rendered (or an error)
list-layouts / save-layout List/persist layout files on the device

The apply-layout echo is the important one: a push reports back the structure the device actually rendered (a control dropped on decode won't appear), so the client never assumes a blind "success."

The MCP server (carter-mcp)

carter-mcp exposes these as tools an LLM (e.g. Claude) can call:

  • Docs: list_controls, get_control_doc, get_layout_schema, list_sample_layouts, get_sample_layout.
  • Pairing: connect, show_qr, wait_for_device, disconnect.
  • Authoring: push_layout (truthful apply-layout echo), save_device_layout, list_device_layouts.
  • Read-back: get_device_layout, get_control_state, get_connection_status.

Hassle-free transport

connect() defaults to target="local": it spins up an in-process, auth-free MeshSocket relay on your machine and builds the QR with your LAN IP — no gateway, no token, no cloud. Put the phone on the same Wi-Fi and scan. For remote authoring, connect(target="relay") uses the Connect+ gateway and auto-mints a token from the dev validator, so you still don't hand-paste credentials.

A typical loop

connect()                         # zero-config local relay + QR
show_qr()                         # (or scan the QR connect() returned)
wait_for_device()                 # polls the roster until the phone joins
push_layout(<json>)               # device renders it; returns the structural echo
get_device_layout(full=true)      # confirm what's live
get_control_state()               # read values off the device
save_device_layout(<json>)        # persist it on the device
disconnect()

Roster note: wait_for_device polls get_nodes rather than waiting on the membership push, because the relay's identify-time roster broadcast can miss a peer that joins after the authoring client — see Message Reference.

Two ways to author

  • MCP (carter-mcp) — LLM authoring: "describe the dashboard and watch it appear," with live push + read-back. Best for conversational, exploratory design.
  • carterkit — programmatic authoring in Python (Layout, typed build.<control>, bind, validate) plus a CLI. Best for scripted, repeatable layout generation and CI.

Both produce the same layout JSON over the same protocol, so a layout authored either way runs against any data server you build.