Skip to main content
Glama

Server Configuration

Describes the environment variables required to run the server.

NameRequiredDescriptionDefault
CARTER_RELAY_URLNoGateway ws/wss URL for target='relay' connects.
CARTER_MESH_TOKENNoGateway auth token (else auto-minted via a validator).
CARTER_VALIDATOR_URLNoDev validator base URL used to auto-mint a token.
CARTER_LOCAL_RELAY_PORTNoPort for the in-process local relay (default 8765).8765

Capabilities

Features and capabilities supported by this server

CapabilityDetails
tools
{
  "listChanged": false
}
prompts
{
  "listChanged": false
}
resources
{
  "subscribe": false,
  "listChanged": false
}
experimental
{}

Tools

Functions exposed to the LLM to take actions

NameDescription
begin_editA

Start (or restart) the working layout buffer for incremental editing.

Then use add_control / insert_example / update_control / move_control / etc. to edit surgically, preview_buffer to see it, and push_buffer to send it live — without ever re-emitting the whole layout.

The app-authored wiring flow: the user arranges controls in the phone's Layout Editor and saves; begin_edit(from_device_file="my-layout.json") pulls that file here (list_device_layouts shows the filenames), then probe_service + autowire_buffer bind its values, you wire the remaining actions/triggers it reports, lint_against_traffic checks reality, and save_buffer puts the wired layout back on the phone.

Args: name: Layout name (blank-buffer mode). columns, rows: Grid of the first tab (blank-buffer mode). accent: Accent color hex (blank-buffer mode). mode, row_height: First tab's grid mode ("grid" default 2-D / "flow") and 2-D row-unit height in points (blank-buffer mode). from_sample: Seed from a sample layout filename (e.g. 'demo-offline.json'). from_device: Seed from the layout currently live on the paired device (read-modify-write). from_device_file: Seed from a SAVED layout on the device by filename or display name (the phone-editor handoff), whether or not it's active.

preview_bufferA

Show the current working buffer: structure, per-tab grid maps, and any placement issues. Never re-dumps the whole JSON (use get_buffer_json for that).

get_buffer_jsonA

Return the full JSON of the working buffer (for inspection or manual save).

add_controlA

Add one control to the buffer. Auto-assigns a unique id and (if no position is given) the next free grid slot honoring the control's default span.

Args: control_json: A single control object, e.g. {"type":"gauge","label":"Battery"}. tab_index: Which tab to add to (default 0). position: Optional [row, col]; omit to auto-place.

insert_exampleA

Drop a documented control example straight into the buffer, with a fresh id and a free grid slot. Browse with list_control_examples, then place one here.

Args: control_id: Control type or doc node-id (e.g. 'gauge'). name: Example name (prefix match); omit for the first example. tab_index: Which tab to add to. position: Optional [row, col]; omit to auto-place.

update_controlA

Merge fields into an existing control. Set a field to null to remove it.

Args: control_id: id of the control to edit. patch_json: Object of fields to merge, e.g. {"tint":"#FF0000","style":"ghost"}.

remove_controlB

Remove a control from the buffer by id.

move_controlB

Reposition / resize a control, or move it to another tab.

Args: control_id: id of the control. position: New [row, col]. span: New [rowSpan, colSpan]. tab_index: Move to this tab index.

add_tabA

Add a tab to the buffer. Returns its index.

mode: "grid" (default 2-D — controls span row x col) or "flow" (legacy row-banded; use for a full-page map/chat/cardList or a plain form). row_height: points per row-unit in 2-D mode (default 56).

add_groupA

Add a group container to the buffer (auto-placed unless position given). Nested children are normalized like add_control: each gets an id and an auto-placed position in the group's own grid.

Args: group_json: A group object, e.g. {"label":"Lights","grid":{"columns":2,"rows":2},"children":[...]}. tab_index: Which tab to add to. position: Optional [row, col].

show_gridA

ASCII occupancy map of a tab's grid — which cells are filled (by which control) and which are free. 'See' the layout spatially before editing.

discard_bufferA

Discard the working buffer without sending anything.

validate_layoutA

Lint a layout against the control schema WITHOUT pushing it: duplicate ids, unknown control types, unknown/bad-enum fields, and grid overlaps/out-of-bounds.

Args: layout_json: Complete layout JSON string.

validate_bufferA

Lint the working buffer against the control schema (same checks as validate_layout) before you push or save it.

snapshot_bufferB

Save a snapshot of the working buffer so you can revert later.

list_snapshotsB

List saved buffer snapshots.

revert_bufferA

Restore the working buffer from a snapshot (default the most recent).

Args: index: Snapshot index (see list_snapshots); -1 = latest.

push_layoutA

Push a layout to the paired device. The device renders it immediately.

When a single device is paired, this pushes over routed RPC and reports back exactly what the device rendered (or why it rejected the layout) — no more blind "pushed successfully". With no resolvable device it falls back to a broadcast so every paired viewer updates at once.

Args: layout_json: Complete layout JSON string. Must be valid LayoutConfig.

save_layoutB

Push a layout and tell the device to save it to disk permanently.

Args: layout_json: Complete layout JSON string. Must be valid LayoutConfig.

push_bufferA

Push the working buffer to the paired device (truthful apply with a rendered echo when a single device is paired). Edits stay in the buffer for further work.

save_bufferB

Push the working buffer AND tell the device to persist it to disk.

Args: filename: Optional filename (derived from the layout name if omitted).

get_device_layoutA

Read the layout currently live on the paired device (structural summary).

Lets you SEE what's on the phone before editing, instead of pushing blind.

Args: full: If true, also include the complete layout JSON (default: summary only).

get_control_stateA

Read the current values of controls on the paired device.

Args: ids: Optional list of control ids to filter to. Omit for all controls.

get_connection_statusA

Read the paired device's relay connection status — whether it's connected, on which channel/account, and which events it's listening on.

get_device_infoA

Read the paired device's CAR-TER app version, build, and protocol version.

Use this to confirm the phone's installed app understands the control definitions you're authoring against. An older app silently drops controls or fields it doesn't recognize — see check_sources for a full drift verdict.

check_sourcesA

Report where the MCP is pulling truth from, and flag any drift.

CAR-TER's MCP is a thin local tool layer over live sources: control DEFINITIONS come from the website catalog (carterbeaudoin.net/CAR-TER), and authoring DEMOS come from the installed carterkit. This shows the catalog version/freshness/fingerprint, installed-vs-latest carterkit, and — when a device is paired — the phone's app/protocol version, then gives an alignment verdict.

Run this at the start of a session, and again whenever a pushed layout behaves unexpectedly, to catch the case where the site, the kit, and the app have drifted out of sync.

Args: refresh: Force a fresh fetch of the website catalog + PyPI version, bypassing the local cache.

list_device_layoutsA

List all layout files stored on the paired device.

Returns the name, filename, tabs, and accent color of each layout. The device must be connected and paired first via connect.

save_device_layoutA

Create or update a layout file on the paired device.

The layout is written to the device's Layouts folder. If a file with the same name already exists, it is overwritten.

Args: layout_json: Complete layout JSON string. Must be valid LayoutConfig with a "name" field. filename: Optional filename (e.g. 'my-layout.json'). Derived from the layout name if omitted.

customize_on_phoneA

Hand a control to the phone's on-screen configurator so the USER customizes it by hand (live preview + field editor), then read back exactly what they shaped.

"Shape it on glass, wire it on the model": the human does the look/feel, you do the plumbing. The user taps "Send to Editor" on the phone to return the control. Requires a paired device in a live-edit session (connect + scan QR).

Args: control_json: The control to hand off (e.g. {"type":"gauge","label":"Battery"}). timeout: Seconds to wait for the user to finish (default 120). add_to_buffer: If true, drop the returned control into the working buffer. tab_index: Tab to add to when add_to_buffer is set.

list_controlsA

List all available CAR-TER control types and system features.

For placeable controls the type shown is the exact camelCase token to put in a layout ({"type": "statusLight"}). The docs: id in parentheses is the kebab-case key for get_control_doc / list_control_examples / insert_example — they differ for multi-word controls (type statusLight ⟷ docs status-light), so don't put the docs id in a layout.

get_control_docA

Get the full documentation for a specific control type or system feature.

Args: control_id: The control identifier (e.g. 'button', 'gauge', 'sync', 'layout-config')

list_sample_layoutsA

List all available sample layout files that can be used as references.

get_sample_layoutB

Get the full JSON of a sample layout file.

Args: name: Filename (e.g. 'demo-offline.json') or name without extension

get_layout_schemaA

Get the layout JSON structure reference showing all fields and their types.

get_control_catalogA

Machine-readable schema for every placeable control, in ONE call.

Returns compact JSON keyed by control type (the value used in a layout), each with its fields (name/type/enum values/default), defaultSpan, and example names. Prefer this over reading individual control docs when authoring — it's the whole control vocabulary at once.

Args: types: Optional list of control types/node-ids to filter to (e.g. ['gauge','button']). include_theme: Also include each control's per-control theme override fields.

list_control_examplesA

List the named example snippets available in a control's documentation.

Use get_control_example to fetch one as a ready-to-tweak config.

Args: control_id: Control type or doc node-id (e.g. 'gauge', 'color-picker').

get_control_exampleA

Get a ready-to-customize JSON config for a documented control example.

Copy it, tweak the fields, then place it into a layout (or use insert_example to drop it straight into the working buffer with a fresh id + free grid slot).

Args: control_id: Control type or doc node-id (e.g. 'button', 'gauge'). name: Example name (prefix match, case-insensitive). Omit for the first example.

infer_layoutA

Infer a wired first-draft layout from a real JSON payload (paste a sample from your service, or use probe_service to capture one). Numbers→gauges, 0..1→progress rings, bools→toggles, lat/lng→map, arrays→sparklines/cardlists, strings→labels — each bound to the right nested valuePath.

Args: payload_json: A sample JSON object emitted by your service. name: Layout name. event: The mesh event the controls should listen on (default 'telemetry'). columns, rows: Grid of the inferred tab. into_buffer: Load the result into the working buffer for further editing (default).

autotune_gaugeA

Tune a buffer gauge from observed samples: sets min/max and color zones at the data's percentiles, oriented by whether higher is better (battery) or worse (temp), inferred from the field name.

Args: control_id: id of a gauge in the working buffer. samples_json: JSON array of numeric samples, e.g. [40,52,61,73,95]. field_name: Metric name for unit/direction hints (defaults to the id).

list_theme_vibesA

List the built-in theme vibes you can generate with generate_theme.

generate_themeA

Generate a layout theme from a vibe description or a brand color, and (by default) apply it to the working buffer.

Args: description: Free text, e.g. 'fighter jet HUD', 'synthwave neon', 'clean apple'. accent: A brand hex color to build the theme around (overrides description). apply_to_buffer: Set the buffer layout's theme + accentColor (default true).

generate_serviceA

Generate a runnable Python MeshSocket service that speaks to a layout — handles the events its controls fire and emits the telemetry they listen for. Uses the working buffer if no layout_json is given.

Args: layout_json: Optional layout JSON; defaults to the working buffer.

generate_adapterA

Generate a REST-poll → MeshSocket adapter that maps an API's fields to a layout's synced valuePaths. Uses the working buffer if no layout_json is given.

Args: base_url: The REST endpoint to poll. layout_json: Optional layout JSON; defaults to the working buffer.

connectA

Pair a device for live layout authoring. Hassle-free by default.

target="local" (default): spins up an in-process, auth-free MeshSocket relay on this Mac and builds a QR with the LAN IP — no gateway, no token, no AWS. Just have the phone on the same Wi-Fi (the app allows ws:// on the LAN).

target="relay": use the Connect+ gateway instead (phone can be on any network, wss). The token is taken from token / CARTER_MESH_TOKEN, or auto-minted from the dev validator (validator_url / CARTER_VALIDATOR_URL) so you still don't hand-paste one.

Args: channel: MeshSocket channel name (default 'editor'). role: MeshSocket role for the editor (default 'editor'). target: 'local' (default, zero-config) or 'relay' (gateway). url: gateway ws/wss URL (target='relay' only); else CARTER_RELAY_URL/default. token: gateway token (target='relay' only); else env, else auto-mint. validator_url: dev-validator base URL to mint a token from (target='relay').

show_qrA

Show the QR code for pairing a device to the current editing session.

Must be connected first via the connect tool.

wait_for_deviceA

Wait for a device to pair after scanning the QR code.

Blocks until a device joins the editing channel or the timeout expires.

Args: timeout: Max seconds to wait (default: 30)

disconnectA

Disconnect from the MeshSocket relay and end the editing session.

probe_serviceA

Listen to the live mesh and report the service's data schema: which events and fields it emits, their value types, ranges, and examples. Run this, then autowire_buffer / lint_against_traffic / infer_layout can use what was discovered.

Args: seconds: How long to listen (default 8). event: The mesh event to sniff (default 'broadcast', the data channel).

simulateA

Emit a data frame onto the channel as if from the service — drives any synced controls so gauges move and sparklines fill (live demo / no-backend testing).

Args: payload_json: The frame to emit, e.g. {"battery":82,"cpu_temp":61}. event: Event to emit on (default 'broadcast').

set_control_valueB

Drive one buffer control live by emitting a frame at its bound valuePath.

Args: control_id: id of a control in the working buffer (must have a listen sync). value_json: The value to push, e.g. 82 or "online" or true.

autowire_bufferA

Bind unbound display controls in the buffer to fields discovered by the last probe_service run (matched by name), then report what still needs wiring — values without a match AND input controls without an action (the triggers half, which needs the server's command vocabulary, i.e. you). Run probe_service first.

lint_against_trafficA

Check the buffer's sync valuePaths against fields seen by the last probe; flags bindings that would silently show no data (wrong path / namespace).

lint_dynamic_trafficA

Check the buffer's dynamic= groups against the broadcasts seen by the last probe: events that never arrive, payloads missing a children array, and injected children that won't render (unknown type, bad enum, id clash, off-grid placement). Run probe_service first. The dynamic-content counterpart to lint_against_traffic.

show_mesh_graphB

Visualize the live MeshSocket network on the device — builds a graph layout and pushes the current roster as animated nodes/edges. "Show me my mesh."

Replaces the working buffer with the mesh layout.

Args: name: Layout name.

run_scenarioA

Drive the device through a scripted scenario and assert control states — UI testing over the mesh, no XCUITest.

Each step: {"emit": {...frame...}, "event": "broadcast", "wait": 0.5, "expect": {"control_id": expected_value, ...}}. emit pushes a data frame; after wait seconds the named controls are read back and compared to expect.

Args: steps_json: JSON array of step objects.

say_in_chatA

Post a message into a layout's channel chat control as the LLM — the in-app agent surface. Requires a paired device showing a chat control.

Args: text: The message to send. sender_name: Display name to send as (default 'Claude').

read_chatA

Listen for incoming chat messages for a while and return them — so the LLM can answer what users type in an in-app chat control.

Args: seconds: How long to listen (default 15).

Prompts

Interactive templates invoked by user choice

NameDescription

No prompts

Resources

Contextual data attached and managed by the client

NameDescription

No resources

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Mariner10/carter-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server