Docs menu
Reference

MCP

Let AI assistants read, configure and run a Tangle project through the Model Context Protocol, with show protection.

tangle-core includes an MCP (Model Context Protocol) server, so an AI assistant can read a project, build rooms and cue lists, control devices and check monitoring. Every tool goes through the same command layer as the REST API: the same validation, scopes and audit log, plus a protection that keeps assistants away from a running show.

Two ways to connect

TransportWhereFor
Streamable HTTPhttp://<host>:7340/mcpAssistants and tools that speak MCP over HTTP.
stdio bridgetangle-core mcpDesktop assistants that only start MCP servers as local commands.

Both need a running tangle-core and an API token. Create a token for the assistant on the machine that runs tangle-core:

tangle-core token create --name claude --scopes read,control,configure

The secret is printed once. Choose the scopes for what the assistant should be able to do (see Scopes).

Note: MCP access is part of Tangle Pro and Ultimate (and the demo mode). On other editions, MCP requests get 403 not_licensed. See Licensing.

Streamable HTTP

Send the token as a bearer token on every request:

POST /mcp HTTP/1.1
Host: 127.0.0.1:7340
Authorization: Bearer tgl_...
Accept: application/json, text/event-stream
Content-Type: application/json

A request without a valid token gets 401 with a problem-details body. Unless tangle-core runs with --allow-remote, the MCP endpoint accepts only requests addressed to this machine (a loopback Host).

stdio bridge

tangle-core mcp reads JSON-RPC messages from stdin, forwards each one to the running core's /mcp endpoint, and writes every answer and notification to stdout.

TANGLE_TOKEN=tgl_... tangle-core mcp
tangle-core mcp --url http://10.0.0.5:7340 --token tgl_...
OptionDefaultDescription
--url <url>http://127.0.0.1:7340Address of the running tangle-core.
--token <token>TANGLE_TOKENAPI token. Reads the TANGLE_TOKEN environment variable when not given.

If the core cannot be reached, the bridge answers each request with a JSON-RPC error that says so. When stdin closes, the bridge ends its MCP session and exits.

Configure an assistant

Most desktop assistants read a JSON file that lists MCP servers. Add Tangle with the bridge:

{
  "mcpServers": {
    "tangle": {
      "command": "tangle-core",
      "args": ["mcp"],
      "env": { "TANGLE_TOKEN": "tgl_..." }
    }
  }
}
  • If tangle-core is not on the assistant's PATH, give its full path in command.
  • To reach a core on another machine, add "--url", "http://10.0.0.5:7340" to args. That core must run with remote access (--listen 0.0.0.0:7340 --allow-remote --insecure-http, see CLI).
  • Restart the assistant after editing its configuration.

The server introduces itself as tangle-core and gives the assistant these instructions: read the project with get_project and live state with get_snapshot; change the configuration with the create_*, update_* and delete tools (dry run first); make things happen with send_intent; drive shows with control_timeline; never interrupt a running show without being asked.

Scopes

Each tool needs one scope (shown in its description, which the assistant reads).

ScopeAllows
readEvery tool that only reads: get_*, list*, search_fixture_library, export_project, device_references.
controlMaking things happen: send_intent, control_timeline, run_automation, stop_automation, set_variable, set_control, press_control, call_function, lighting playback and programmer, rebalance_cluster, resume_session, alerts and metrics, device log notes, positions.
configureChanging the project and the core: create_*, update_*, delete, remove_devices, drivers, modules, projects, templates, dashboards drafts and publishing, tests, discovery, setup assistants, community.
adminmanage_license, accept_discovered_core, get_pairing_code.
liveAllows changes and control while a timeline plays (see below).

The tables below give each tool's scope.

Resources and live updates need read.

Show protection

While any timeline is playing, an assistant whose token lacks the live scope cannot change anything. Every tool that edits the project, sends an intent, drives a timeline or runs an automation is refused with code show_running:

{
  "type": "https://tangle.dev/problems/show_running",
  "title": "Conflict",
  "status": 409,
  "detail": "the show is running (timeline main-show is playing); nothing was changed",
  "code": "show_running"
}

Reading always works. Give a token live only when an assistant should act during a show:

tangle-core token create --name show-assistant --scopes read,control,live

Other protections apply to every client, with or without live:

  • Live timelines: editing a timeline (or its tracks and cues) while it plays is refused (timeline_running) unless the tool call sets allowLive: true.
  • Network scans: discover_devices is refused while a timeline plays (show_mode).
  • Deleting: delete only previews unless confirm is true.
  • Redundancy: on a backup node, changes and control are refused with not_primary.

Results and errors

Tool results are JSON (structured content). A list is wrapped as { "result": [...] }. When a tool fails, the result is an error whose content is a problem-details object with a stable code, detail and, for validation errors, errors listing each problem. The codes are the REST API's (see REST API errors); an unknown tool name gets unknown_tool.

Configuration tools (create_*, update_*, delete) return:

FieldDescription
dryRunTrue when nothing was applied.
resultThe resource after the change (or as it would be). Absent after a delete.
changes[{ op, kind, id, parent }]: what changed.
revisionProject revision after the change.
noteOn a delete without confirm: says nothing was deleted.

Tools

Project and configuration

ToolScopePurposeArguments
get_projectreadRead the whole project.none
list_modulesreadInstalled device modules with their capabilities and the devices using each.none
get_cluster_statusreadRedundancy status: role, primary, every node's health, sync state and cue log.none
listreadList resources of one kind, the tracks of a timeline, or the cues of a track.kind (required), timelineId, trackId
getreadRead one resource by id.kind, id (required), timelineId, trackId
deleteconfigureDelete a resource. Without confirm: true it only previews. Refused if the project would become invalid (for example a scene still uses the device).kind, id (required), timelineId, trackId, confirm, dryRun, allowLive
create_<kind>configureCreate a resource. The whole project is validated first; a mistake changes nothing.<kind> (the resource, required), timelineId, trackId, dryRun, allowLive
update_<kind>configureReplace a resource with a complete new version (read it first with get). Creates it if missing.same as create_<kind>

kind for list, get and delete is one of: room, device, scene, timeline, track, cue, automation, alertRule, notificationChannel, maintenanceWindow, probe. Tracks need timelineId; cues need timelineId and trackId.

The create and update tools exist for every resource type; their input schema is the contract type, so the assistant sees every field:

ToolsArgumentContract type
create_room, update_roomroomRoom
create_device, update_devicedeviceDeviceInstance
create_scene, update_scenesceneScene
create_timeline, update_timelinetimelineTimeline
create_track, update_tracktrack, timelineIdTrack
create_cue, update_cuecue, timelineId, trackIdCue
create_dashboard, update_dashboarddashboardDashboard
create_automation, update_automationautomationAutomation
create_alertRule, update_alertRulealertRuleAlertRule
create_notificationChannel, update_notificationChannelnotificationChannelNotificationChannel
create_maintenanceWindow, update_maintenanceWindowmaintenanceWindowMaintenanceWindow
create_probe, update_probeprobeProbe
create_listener, update_listenerlistenerListener
create_map, update_mapmapMap
create_view, update_viewviewEndUserView
create_sequence, update_sequencesequenceSequence
create_preset, update_presetpresetLightingPreset
create_lightingGroup, update_lightingGrouplightingGroupLightingGroup
create_executor, update_executorexecutorExecutor

The fields of each type are in Project file. dryRun: true validates and returns the changes without applying them. Device settings are checked against the module's settings schema, and secret settings go to the OS credential store.

ToolScopePurposeArguments
list_available_modulesreadEvery module this core knows: installed, update available, or bundled and ready to install.none
install_moduleconfigureInstall or update a module. Devices using it restart; refused while a timeline plays if any would.moduleId
device_referencesreadWhat uses these devices and their sub-devices. Call it before remove_devices.ids
remove_devicesconfigureDelete devices, their sub-devices and their references in one change. Without confirm: true it only previews.ids, references (remove or keep), confirm, allowLive
run_device_setupconfigureRun one step of a device's setup assistant through its module. Settings it returns are saved on the device.deviceId, configurator (required), step, answers, config
list_units, set_project_unitsread, configureThe quantities and units Tangle converts between; the project's metric or imperial system and overrides.system, overrides, autoScale
set_project_controlsconfigureThe project's default dashboard control style and highlight colours.controls, colors
get_variables, set_project_variablesread, configureProject variables with their values; declare the whole list.name; variables
list_project_templates, apply_project_templateread, configureThe kinds of project the wizard starts from; add one to the project (rooms, planned devices, timelines, automations, dashboards, alert rules).templateId, answers, devices, acknowledged, dryRun

Project library

ToolScopePurposeArguments
list_projectsreadThe open project and every project kept on this core.none
create_projectconfigureA new, empty project; open: true opens it.name (required), id, open
open_project, close_projectconfigureOpen another project, or close the open one. Refused while a timeline plays unless force (needs live).projectId, force
duplicate_projectconfigureCopy a project with its dashboards and plans; open: true is Save as.projectId, name, open
rename_projectconfigureGive a project a new name; its id, dashboards and plans stay.projectId, name
delete_projectconfigureDelete a project that is not open. Cannot be undone.projectId
export_project, import_projectread, configureA .tangle file as base64, without device passwords; import one, or a Project object, as a new project.projectId; dataBase64 or project, fileName, open
save_projectconfigureWrite the open project's file now.none

Control and live state

ToolScopePurposeArguments
send_intentcontrolMake something happen (power.on, level.set, input.select, scene.recall with params.scene, ...) on a device, room, tag or everything. Waits for the result and returns the final IntentStatus with each device's outcome.intent (an IntentRequest, required), waitMs (0 to 60000, default 5000)
get_intent_statusreadCurrent status of an intent sent earlier.intentId
control_timelinecontrolPlay, pause, stop, seek (positionMs) or GO (cue lists). Returns the TimelineState.control: { op, timelineId, positionMs }
get_timeline_statesreadTransport state of every timeline (status, position, last and next cue).none
get_snapshotreadLive status and state of every device, and every timeline's state.none
get_device_statereadLive status and capability state of one device; use it to diagnose a device.deviceId
test_deviceconfigureTest a device's connection in a separate module process (the running device is not touched). Pass config to try settings before saving them.deviceId (required), config
discover_devicesconfigureScan the local network (mDNS, SSDP) for devices, with suggested modules. Refused while a timeline plays.seconds (1 to 30, default 5)
get_device_logreadA device's log, newest first: actions and who sent them, their outcome, status and state changes, events. Several devices are merged.deviceIds (required), limit, before, kinds, level
add_device_log_note, clear_device_logcontrol, configureWrite a note in a device's log; empty it.deviceId, text, level
set_variablecontrolSet a project variable; variable triggers fire.name, value
list_controlsreadDashboard controls with a kept value or override.id
set_controlcontrolSet a dashboard control: value (or add), label, visible, enabled, other properties in props. Every screen follows.id (required), value, add, label, visible, enabled, props
press_controlcontrolReport a control event as if someone used it: click, press, release or hold.id (required), event, value
rename_controlconfigureRename a control; every reference follows.id, to
list_functions, call_functionread, controlLibrary functions for expressions and Function steps; call one to try it.namespace; name, args

Intents sent over MCP are recorded with source api and the token name. See REST API intents for intent names and targets.

Dashboards

ToolScopePurposeArguments
get_dashboard_draftconfigureRead a dashboard's draft, or its published version when there is no draft.dashboardId
save_dashboard_draftconfigureSave a draft (contract Dashboard). Screens keep the published version until it is published.dashboardId, dashboard
publish_dashboardconfigurePublish the draft: every screen showing the dashboard reloads.dashboardId
list_dashboard_versionsreadPublished versions, newest first.dashboardId
get_dashboard_versionreadOne published version.dashboardId, version
restore_dashboard_versionconfigurePublish an old version again, as a new version.dashboardId, version

create_dashboard and update_dashboard publish directly. See Dashboards.

Automations

ToolScopePurposeArguments
run_automationcontrolRun an automation now. Conditions are checked unless force is true. Returns the run: started, or skipped with the reason.automationId (required), force
get_automation_runsreadRecent runs, newest first: what triggered each, and whether it completed, failed (with the reason) or was skipped.automationId
stop_automationcontrolStop every run of an automation in progress.automationId
run_macro, get_macro_runs, stop_macrocontrol, readDeprecated aliases: macros are automations since contract 0.2.30.macroId

Listeners

ToolScopePurposeArguments
get_listenersreadEvery listener and how it is doing; with listenerId and log: true, the messages it received with the matched rule, captures and runs.listenerId, log, since
get_listener_runsreadRecent runs started by a listener's messages.listenerId
test_listenerconfigureCheck a message against a listener's rules. A dry run unless run: true.listenerId (required), text, http, osc, run

Device creator and community

ToolScopePurposeArguments
list_drivers, get_driver, get_driver_filesreadDrivers made with the device creator: the list, one definition and code, or every file of its module.driverId
check_driverconfigureCheck a definition and its code without saving: errors and warnings with paths.definition (required), script
save_driverconfigureBuild and install a driver's module; devices using it restart. The description explains the definition format.definition (required), script
delete_driverconfigureDelete a driver: uninstalls its module and removes its source; refused while devices use it.driverId
communityread, configureThe community driver repository: status, search, install, publish, sign-in and sign-out.action (required), and the action's arguments

Cluster

ToolScopePurposeArguments
list_discovered_coresreadOther cores on the local network, not in this cluster.none
accept_discovered_coreadminKeep a discovered core separate, or pair it as a backup with its pairing code (ask the user for it).instanceId, mode (required), pairingCode
get_pairing_codeadminThis core's pairing code.none
get_cluster_placementreadShared mode: which node runs each device.none
rebalance_clustercontrolShared mode: spread the devices again. Ask the user first during a show; dryRun previews.dryRun
set_cluster_settingsconfigureStandby or shared mode, folder placement, auto return, the cluster address, health limits.mode, folders, autoReturn, address, limits

Maps, plans and images

ToolScopePurposeArguments
import_plan, get_planconfigure, readImport a floor plan (SVG text, or a DXF, DWG, PNG or JPEG file as base64) for a map; read one back.name, svg or dataBase64; file
import_image, get_imageconfigure, readStore a dashboard image; read one back.name, svg or dataBase64; file
get_map_positionsreadWhat is where on a map, in metres: placed devices and tracked positions.mapId
push_positionscontrolReport positions as a tracking source does.positions

Lighting

ToolScopePurposeArguments
get_lighting_statereadEvery sequence, the grand master and your programmer.none
lighting_commandcontrolGo, back, goto, off, fader, flash, pause, grand master.command
lighting_programmercontrolSelect lights, set values, fan, blind, highlight, clear.update
lighting_storeconfigureStore the programmer into a cue, a preset or a group.store
search_fixture_libraryreadSearch the bundled fixture library by manufacturer or model.query, limit

Monitoring (Sentinel)

ToolScopePurposeArguments
get_sentinel_statusreadOverview: firing alert counts by severity, the firing alerts, the health of every device, core node and probe.none
list_alertsreadPending and firing alerts; with history: true also recent transitions, newest first.history, limit (1 to 500)
ack_alertcontrolAcknowledge an alert: stops its repeat notifications.alertId (required), note
silence_alertscontrolStop notifications for one alert or every alert of a rule until a time.alertId or ruleId, until (ms since epoch, required)
push_metricscontrolRecord custom metric values that metric alert rules can watch.samples: [{ name, value, labels, at }]
get_metricsreadCurrent custom and probe metric values; samples: true adds 24 h of per-minute min/max/last.samples
test_channelconfigureSend a test notification through a channel and return the provider's answer.channelId

Monitoring is part of Tangle Pro and Ultimate. See Sentinel.

License

ToolScopePurposeArguments
get_licensereadState, mode (licensed, designer, demo), edition, features, limits, expiry dates, and whether a designer or demo session is paused.none
resume_sessioncontrolResume device connections and timelines after the hourly pause of the free designer or demo mode.none
manage_licenseadminActivate, refresh, deactivate, import a license file, offline mode, sign in with email, password reset, request file.action (required), key, email, password, licenseId, name, file, offline

Resources

URIContent
tangle://projectThe project configuration.
tangle://snapshotEvery device's status and state, and every timeline's state.
tangle://devices/{deviceId}/stateLive status and state of one device (one resource per device in the project).
tangle://timelines/{timelineId}/stateTransport state of one timeline (one resource per timeline).

All resources are application/json. The two {...} forms are also offered as resource templates.

Assistants can subscribe to resources to be notified when they change:

ChangeResources notified
A device's state or statustangle://devices/<id>/state, tangle://snapshot
A timeline's statetangle://timelines/<id>/state, tangle://snapshot
The projecttangle://project

Prompts

PromptArgumentWhat it asks the assistant to do
set_up_roomroom (room name)List the installed modules, ask which devices are in the room and how to reach them, create the room and each device (dry run first), propose a "presentation" and an "off" scene, then test with scene.recall and report each device's outcome.
build_cue_listshow (what happens, in order)Read the project for real device ids, create a cuelist timeline with one track and one cue per step, validate with a dry run, show the cue list, and apply it only after you agree.
diagnose_devicedeviceIdRead the device's status and configuration, check its module is installed, and explain the likely cause and what to check on site, without changing anything.

Audit

Every change and control action made through MCP is recorded in audit.log (in the Tangle log folder) with surface mcp and the token name, like any other client. Use one token per assistant so the log shows who did what.