AI Agents (MCP)
Let Claude Code, Codex and other MCP clients build and edit Filament projects through a local MCP server.
Filament has a built-in Model Context Protocol server. Turn it on and a coding agent — Claude Code, Codex, Claude Desktop, or any MCP client — can lay out LED strips, address DMX, fill the player grid, arrange a show on the timeline, make looks react to music, write shaders and check the result with live previews, while you watch every change land in the app.
What it does
- Edits the project you have open. Changes appear live, autosave covers them, and every tool call is one undo step (Cmd+Z undoes it).
- Covers the whole project: surfaces, LED curves and fixtures, DMX addressing, warps, video outputs and slices, layers, groups, clips, effect chains, palettes, the timeline with its automation lanes, audio and envelope modulation, and user animation and effect shaders.
- Lets the agent check its work: a PNG of the composite, a layer, a clip or a video output; a picture of the LED layout; LED output values; live audio band levels; shader compile errors; recent logs.
- Runs long jobs in the background. Timeline exports, diagnostics reports and Resolume imports run as MCP tasks in clients that support them, so the agent can follow their progress or cancel them.
Turn it on
Open Settings → AI Agents (or Help → Connect an AI Agent…) and switch MCP server on. Filament creates an access token the first time.
| Field | What it does |
|---|---|
MCP server | Starts the server. It stays on across launches until you turn it off. |
Port | Default 7320. Press Apply after changing it. |
Allow remote connections | Off: only programs on this computer can connect. On: other computers on your network connect at the address shown, with the token. |
Token | The access token clients must send. Copy copies it; Regenerate replaces it; clients added with Add are updated, others need the new one. |
A status-bar dot shows the server state (green when listening) and opens the page when clicked. The Activity list shows each tool call with its duration and result.
Connect a client
Under Connect a client, Filament lists Claude Code, Claude Desktop and Codex and whether each is installed on this computer. Press Add next to one and Filament writes its own entry into that client's configuration, then:
| Client | To start using Filament |
|---|---|
| Claude Code | Start a new session. /mcp lists filament. |
| Claude Desktop | Quit and reopen Claude Desktop. |
| Codex (CLI and the Codex app) | Restart Codex. |
Filament keeps a .filament-backup copy of each file it changes and leaves every other setting alone. Update appears when an entry uses an old port or token; regenerating the token or changing the port updates the clients you added this way automatically. Remove takes the entry out again.
Claude Desktop starts Filament's own executable as a small relay, so it needs no Node.js. If you open Filament from a disk image or the Downloads folder on macOS, move it to Applications first.
Manual setup
The settings page shows each configuration below with your real port, token and Filament path, and a copy button in the corner. Here, replace <PORT> and <TOKEN>.
Claude Code
claude mcp add --transport http --scope user \
filament http://127.0.0.1:<PORT>/mcp \
--header "Authorization: Bearer <TOKEN>"--header must come after the name and URL.
Codex — add to ~/.codex/config.toml (Windows: %USERPROFILE%\.codex\config.toml):
[mcp_servers.filament]
url = "http://127.0.0.1:<PORT>/mcp"
http_headers = { Authorization = "Bearer <TOKEN>" }Claude Desktop — add to claude_desktop_config.json (Settings → Developer → Edit Config in Claude Desktop). command is the Filament executable: /Applications/Filament.app/Contents/MacOS/Filament on macOS, Filament.exe in the install folder on Windows, /usr/bin/filament or the AppImage on Linux.
{
"mcpServers": {
"filament": {
"command": "/Applications/Filament.app/Contents/MacOS/Filament",
"args": ["--mcp-stdio"],
"env": { "FILAMENT_MCP_PORT": "<PORT>", "FILAMENT_MCP_TOKEN": "<TOKEN>" }
}
}
}Other clients (Cursor, Windsurf and others that read .mcp.json)
{ "mcpServers": { "filament": { "type": "http", "url": "http://127.0.0.1:<PORT>/mcp",
"headers": { "Authorization": "Bearer <TOKEN>" } } } }To check the server from a terminal:
curl -s -X POST http://127.0.0.1:<PORT>/mcp \
-H "Authorization: Bearer <TOKEN>" -H "Content-Type: application/json" -H "Accept: application/json" \
-H "Mcp-Method: server/discover" -H "Mcp-Name: curl" \
-d '{"jsonrpc":"2.0","id":1,"method":"server/discover"}'From another computer
Turn on Allow remote connections on the Filament machine, then set up Claude Code, Codex or another HTTP client on the other computer as above, with the address the settings page shows in place of 127.0.0.1. Claude Desktop's relay only reaches Filament on its own computer. The first time, your firewall may ask whether Filament may accept incoming connections.
Permissions
| Setting | Default | Allows |
|---|---|---|
| Allow destructive operations | Off | Deleting projects, fixtures, palettes, shader bundles and media roots — things undo cannot bring back. |
| Allow playback control | On | Starting and stopping playback, launching clips, switching between session and arrangement playback, moving the timeline playhead, exporting the timeline, and opening output windows. |
Everything else — editing the open project — is always allowed while the server is on, and always undoable.
What agents can do
| Area | Tools |
|---|---|
| Projects | Create, open, save, rename, duplicate, import and export .filament files |
| Document | Read the project, find things by name, patch any field, undo and redo, batch many edits into one undo step |
| Mapping | Surfaces and their DMX output, fixtures, LED curves (lines, shapes, LED matrices), loose fixtures, warps, DMX validation and channel maps |
| Player | Columns, layers, groups, clips (animations, video, images, live sources), effect chains, master, palettes, surface routing |
| Arrangement | Timeline clips (add, move, split, join, fades), clip effects, track mute and solo, markers, the loop region, timecode regions, playback mode and transport |
| Automation | Lanes for opacity, volume, brightness and effect parameters (points, preset shapes or an LFO), clip envelopes |
| Modulation | Audio-band and envelope/LFO modulation of clip, effect, layer, group, master and surface parameters; live audio levels for tuning |
| Outputs | Video outputs and slices, Resolume Advanced Output export and import, timeline export to a video file or a .dmxshow bundle |
| Media | Media folders, files, thumbnails and frames, live external sources |
| Shaders | List, read, validate, create, fork, write, import and export animation and effect bundles; compile diagnostics |
| Checking | Preview images, a picture of the LED layout, LED output values, runtime status, logs |
Agents can also read the shader contracts, the animation, effect and palette catalogues, and the document schema as MCP resources. A client that subscribes to filament://project/current hears about your edits as you make them.
Safety
- This computer only, unless you allow remote connections. The server listens on
127.0.0.1by default. With Allow remote connections on, other machines on your network can reach it with the token, which travels unencrypted, so use it on a network you trust. Requests from web pages are always refused. - Token required. Any program with the token can edit your projects while the server is on; regenerate it if it leaks.
- Undo covers edits. Every call is one undo step, and a failed
batchrolls itself back. You and the agent share one undo history, so Cmd+Z in the app can undo an agent's step. - Off by default. Nothing listens until you enable it, and exports keep their usual license rules.
- Exports pause live output. A timeline export renders offline and live output stops until it finishes, so the agent is told to ask before exporting during a show.
Guide for agents
This is the guide agents read from the filament://guide/agent resource.
Read this before you edit a project. Read filament://guide/workflows for step-by-step recipes.
1. What Filament is
Filament maps video onto LEDs and projectors and plays it live.
- Canvas: a 2D pixel space (
canvasWidth×canvasHeight) the content is rendered into. - Surfaces: DMX outputs (Art-Net or sACN, a controller IP, a first universe). A surface holds slices: each slice samples a canvas rectangle into a fixture (a pixel layout and channel order) at a DMX start channel.
- Curves: LED strips drawn as bezier paths. A curve owns one slice per LED and regenerates
them when it changes; its channels run contiguously from
startChannel. - Warps: perspective + mesh deformations that move curves and loose slices together.
- Player grid: columns × layers. A cell holds a clip: an animation (a WGSL shader with parameters), a video, a still image, or a live external source. Layers blend in stack order (0 = bottom); groups composite a contiguous band of layers in isolation.
- Arrangement: the timeline. Each layer has one track; a track's clips carry the same content a grid cell does and play in arrangement mode, with fades, markers, a loop region and timecode regions.
- Effect chains run on a clip, a layer, a group, or the master.
- Palettes colour animations. The project has a master palette; a clip follows it unless
it has a palette of its own (
clip_update { palette: null }makes it follow again). - Video outputs send the composite (or one layer or group) to a projector window, Syphon, Spout, NDI or a file, through slices with their own warp and mask.
2. How this server behaves
- You edit the live document. The operator sees every change in the app as it lands, and autosave covers it. Nothing here writes files behind the app's back.
- One tool call is one undo step.
undoandredoact like Cmd+Z / Cmd+Shift+Z.batchruns many calls as one step and rolls them all back if one fails — use it for multi-step builds. - The undo history is shared with the operator. An edit made in the app between your edit
and your
undois the one that gets undone. Pass the revision your edit returned asundo { expectedRevision }to undo only your own step; the reply'sbyAgentsays whose step it reverted. - Revisions. Every editing tool returns
revision. Pass it back asexpectedRevisionon the next edit: if the operator changed the document in between, you getrevision_conflictand nothing is applied; re-read (project_get_current,document_get) and retry. Revisions reset when the app reloads. - Watch instead of polling. Subscribe to
filament://project/current(any change, a project switch included) orfilament://project/current/timeline(arrangement changes) to hear about the operator's edits; notifications come at most every 250 ms. Your own edits notify too: compare the resource'srevisionwith the one your call returned. A client that cannot subscribe can compareserver_info'srevisioninstead. - Names or ids. Every reference (
surface,layer,curve,fixture, …) takes an id or a name: exact id, then exact name, then case-insensitive name. Several matches giveambiguous_namewith the candidates. A grid clip is{ layer, column }; an arrangement clip is{ track, clip }, wheretrackis its layer. An effect target is"master",{ layer },{ group },{ layer, column }or{ track, clip }. - Permission gates. Tools that delete library items (projects, fixtures, palettes, shader
bundles, media roots) need "Allow destructive operations" (
destructive_disabledotherwise). Playback tools (transport_set,clip_launch,column_launch,layer_stop,stop_all,tempo_tap,playback_mode_set,timeline_transport,timeline_export, output windows) need "Allow playback control" (audition_disabled).server_infosays which are on. - Not undoable: library and file tools (fixtures, palettes, shader bundles, media roots, exports, project create/open/delete) and playback state. Removing a surface or a layer from the open document is undoable.
- Read-only projects. A project that loaded with unreadable data refuses edits with
read_only_project.project_clear_read_onlylifts it; the next save overwrites the bytes that could not be read. - The app must be open. Without the main window, editing tools fail with
app_window_unavailable; retry once the window is back. - Errors carry
code,messageanddetails.validationmessages name the field and the allowed values; fix the argument rather than retrying.
3. Recipes
The full sequences are in filament://guide/workflows. In short:
- Start a project:
project_create→fixture_presets_list/fixture_list→surface_create→curve_add_line/curve_add_grid/curve_add_shape→dmx_validate→canvas_render_layout. - Build a grid of looks:
column_add→layer_add→animation_list→clip_assign_animation→effect_add→palette_set_project→clip_launch→preview_render. - Arrange a show:
timeline_marker_add→timeline_clip_add { source: { cell } }→timeline_clip_update(fades) →playback_mode_set { mode: "arrangement" }→timeline_transport→preview_render. - Write a shader: read
filament://docs/animation-contract→shader_template_get→animation_validate→animation_create→animation_write_source→clip_assign_animation→preview_render→shader_diagnostics. - Route outputs:
surface_routing_set,video_output_create,video_slice_add,preview_renderwith{ videoOutput }. - Hand off:
project_save,project_export_file,export_resolume.
4. Pitfalls
- Decoded vs stored shapes. Tools speak the decoded document the app edits
(
filament://schema/document): surfaces carryipAddress,startingUniverseandoutputDevice; curves live indocument.curves, not inside surfaces.filament://schema/projectis the stored/archive shape — read it for leaf types, not for editing. - Curves belong to a surface. A curve's LEDs are slices on one surface. Create curves with
the curve tools (they pick the surface's next free channel unless you give
startChannel); do not add slices for curve LEDs yourself. - Curve LEDs are derived. Change a strip with
curve_update/curve_transform; a curve LED's slice only takesname,enabled,flipand output offsets. - Effect instance ids are minted by the app.
effect_addreturns the new instance; use itsidwitheffect_update,effect_move,effect_remove. - Parameters are checked.
clip_assign_animationrefuses unknown parameter ids (listing the valid ones) and clamps numbers to their declared range, reporting what it clamped. - Player edits need the player. Right after opening a project the runtime is still loading
it; player tools return
app_window_unavailablefor that moment — retry. preview_renderneeds the runtime ticking. If it times out, ask the operator to open the Player page or a preview window.- Launches crossfade.
clip_launchandcolumn_launchreturncrossfadeMs; a preview rendered before that has passed still shows part of the previous clip. - Exports need a paid license (
license_required_for_exporton trial installs). - Thumbnails and slices are left out by default (
document_getincludeThumbnails,includeSlices;curve_listincludeSliceIds) to keep replies small. - Removing library items checks the open project only; other projects in the library may still use them.
- New video outputs start off. Turning on a display output opens a window on a projector; ask before doing that in front of an audience.
5. Arranging a show
- Time arguments are seconds from the start,
{ bar, beat? }(1-based, 4/4 at the master BPM;{ bar: 1 }is 0 s) or{ marker, offset? }. Lengths are seconds,{ beats }or{ bars }. Replies give seconds, withbar("9.1") when the time lands on a beat. Set the BPM (master_update) before placing by bars. - Tracks follow layers. Add or remove a layer with
layer_add/layer_remove; its track comes and goes with it. - Overlaps. A track plays at most two clips at once, and only as a crossfade: the later clip starts and ends after the earlier one. Anything else is refused with the clip in the way named; nothing is shifted for you.
- Arrangement clips are copies.
timeline_clip_add { source: { cell } }copies the cell; editing the cell later does not change the clip. Edit the clip withtimeline_clip_updateand its chain with the effect tools andtarget: { track, clip }. - Ids from the app.
timeline_clip_splitreturns both halves with new ids, andeffect_addreturns an arrangement clip's new instance; use those ids next. - Automation. A lane belongs to a track, to
"master"or to{ group }and drives one target:"opacity","volume","brightness","masterVolume",{ effect, parameter }or{ effect, mix: true }. Read ranges withtimeline_lane_targets; values are in the target's own units and clamped. A lane is points (timeline_lane_set,timeline_lane_shapewith a shape fromfilament://registry/enums) or an LFO (timeline_lane_generator_set), never both. Rate knobs take onlylinear/holdpoints. Envelopes that travel with a clip aretimeline_clip_envelope_set. - Exporting pauses the show.
timeline_exportrenders a video file and/or a.dmxshowbundle offline (paid license, playback control allowed), and live output stops until it finishes. Ask before exporting during a show. Clients with MCP Tasks get a task to poll; others get the result inline only for short ranges, elsetask_required: export the loop region or a span between markers instead. One export runs at a time (conflict). - Arrangement mode. Clips play only in arrangement mode (
playback_mode_set), andtimeline_transportrefuses in session mode or while timecode chase is armed.
6. Making it react
- Two sources.
modulation_audio_setmakes a parameter follow an audio band;modulation_envelope_setdrives it with an envelope/LFO in beats or seconds. A target is a cell parameter{ layer, column, parameter }, an effect{ effect: { target, instance }, parameter }or itsmix: true,{ layer, field },{ group, field },{ master }or{ surface, field }. One modulation per target: setting it again replaces the source. - Cell targets stay on the grid. A cell parameter modulation drives that grid cell only,
never an arrangement clip copied from it. In the arrangement, modulate the layer, group,
master or an effect, and give clips
timeline_clip_envelope_set. - Pick the band by ear. Start from a preset (
audio_presets_list:kick,bass-pump,snare-clap,hat-shimmer,mid-vocal), then callaudio_levels_getwith music playing. Setthresholdnear the band'sfloorandgainso itsp95lands near 0.8.gainstops at 4: a quiet input (a laptop microphone) needs acurvebelow 1 as well. Afterwardsaudio_levels_get { modulations: [id] }shows the values the parameter really takes. Ahintsays when the input is off or silent; turning input on is the operator's job (Settings → Audio). - Prefer envelopes for anything that must repeat. Audio and MIDI modulation render at their base values in exports; an envelope synced in beats plays the same every time.
- Lanes win in arrangement mode. While the arrangement plays, a target with an
automation lane follows the lane and its modulation pauses (
shadowedByLaneinmodulation_list).
7. Limits
| Limit | Value |
|---|---|
| Layers per grid | 32 |
| Effects per chain | 16 |
| Slices per video output | 64 |
| LEDs per curve | 4096 |
| Canvas size | 16–16384 px per side |
| WGSL source | 256 KB |
| Bundle manifest | 64 KB |
Calls per batch | 500 |
Settings
Configure Filament — auto-save, performance, theme, media and Resolume paths, audio, MIDI, OSC, Art-Net input, AI agents, tempo sync, your license, and diagnostics.
Export to Resolume
Hand your mapping off to Resolume Advanced Output XML, review the sACN-to-Art-Net conversion, and keep Filament current with the in-app updater.