Skip to main content
Glama
bigsbypuglise

Fusion Studio MCP

Fusion Studio MCP

Local MCP server for inspecting and controlling standalone Blackmagic Fusion Studio through Fusion's scripting API.

This project starts conservatively: prove the Fusion connection first, then expose read-only inspection tools, then add guarded edit tools with dry-run and undo behavior.

Current Status

  • Project scaffold created: 2026-07-13

  • Target app found: Blackmagic Fusion 21.0.2

  • Python import path confirmed for Fusion's bundled fusionscript.so

  • Live composition inspection verified against Composition1

  • Local .venv created with pytest, ruff, and the Python MCP SDK

  • Read-only MCP tools implemented for status, node listing, single-node lookup, selected-node reads, and compact comp summaries

  • Guarded editing MCP tools implemented for selection, input reads/writes, renaming, and FlowView positioning

  • Controlled node creation, image connection editing, input disconnect, connection inspection, and confirmed single-node deletion implemented

  • Configurable node creation plus native keyframe and expression tools implemented

  • Composition controls plus transactional graph and batch tools implemented

  • Render validation, Saver settings, diagnostics, tool catalog/schema, and graph export tools implemented

  • Live editing validation passed against disposable Composition1

Related MCP server: resolve-mcp

Requirements

  • macOS

  • Blackmagic Fusion Studio 21.0.2 or compatible

  • Python 3.11+ recommended

  • Fusion's bundled scripting library path available: /Applications/Blackmagic Fusion 21/Fusion.app/Contents/Libraries

  • Python MCP SDK for server mode

Installation

The macOS workflow below has been live-tested with Fusion Studio 21.0.2. The Windows workflow is documented for equivalent Fusion Studio installs, but still needs clean-machine validation on Windows.

macOS

Supported live-tested environment:

  • Blackmagic Fusion Studio 21.0.2

  • Python 3.11+

  • Confirmed app path: /Applications/Blackmagic Fusion 21/Fusion.app

  • Confirmed scripting library path: /Applications/Blackmagic Fusion 21/Fusion.app/Contents/Libraries

Install Python with Homebrew if needed:

brew install python@3.11

Create and install the local environment:

cd /path/to/fusion-studio-mcp
PYTHON_BIN=/opt/homebrew/bin/python3.11 scripts/setup_local.sh

Or do it manually:

cd /path/to/fusion-studio-mcp
python3 -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install -e '.[dev]'

Start Fusion Studio, create or open a disposable composition, then run:

export PYTHONPATH="/Applications/Blackmagic Fusion 21/Fusion.app/Contents/Libraries:src"
python scripts/test_fusion_connection.py
python -m fusion_mcp.server

python -m fusion_mcp.server is a stdio MCP server entrypoint. It is meant to be launched by an MCP client; when run directly in a plain terminal without a client attached, it may exit cleanly after stdin closes. Use scripts/test_fusion_connection.py for a standalone connection smoke test.

macOS MCP client example:

{
  "mcpServers": {
    "fusion-studio": {
      "command": "/path/to/fusion-studio-mcp/.venv/bin/python",
      "args": ["-m", "fusion_mcp.server"],
      "env": {
        "PYTHONPATH": "/Applications/Blackmagic Fusion 21/Fusion.app/Contents/Libraries:/path/to/fusion-studio-mcp/src"
      }
    }
  }
}

macOS troubleshooting:

  • If Fusion is closed or no comp is active, connection tools return FUSION_NOT_RUNNING or NO_ACTIVE_COMP.

  • If fusionscript cannot import, confirm PYTHONPATH includes Fusion's Contents/Libraries path.

  • macOS may show security prompts the first time tools communicate with another app. Allow Fusion and the terminal/MCP client to communicate locally.

  • Use unique absolute output folders for Saver renders to avoid overwrite protection and Fusion filename edge cases.

Windows

Documented target environment:

  • Blackmagic Fusion Studio 21.0.2 or compatible

  • Python 3.11+

  • Common app path: C:\Program Files\Blackmagic Design\Fusion 21\Fusion.exe

  • Common scripting library path: C:\Program Files\Blackmagic Design\Fusion 21

Install Python from https://www.python.org/downloads/windows/ and enable "Add python.exe to PATH", or install with winget:

winget install Python.Python.3.11
python --version
py -3.11 --version

Create and install the local environment from PowerShell:

cd C:\path\to\fusion-studio-mcp
.\scripts\setup_local.ps1 -Python py -PythonArgs "-3.11"
.\.venv\Scripts\Activate.ps1

If PowerShell blocks the script, run it for the current process only:

Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass
.\scripts\setup_local.ps1 -Python py -PythonArgs "-3.11"

Manual Command Prompt setup:

cd C:\path\to\fusion-studio-mcp
py -3.11 -m venv .venv
.venv\Scripts\activate.bat
python -m pip install --upgrade pip
python -m pip install -e .[dev]

Start Fusion Studio, create or open a disposable composition, then run from PowerShell:

.\.venv\Scripts\Activate.ps1
$env:PYTHONPATH = "C:\Program Files\Blackmagic Design\Fusion 21;C:\path\to\fusion-studio-mcp\src"
.\.venv\Scripts\python.exe .\scripts\test_fusion_connection.py
.\.venv\Scripts\python.exe -m fusion_mcp.server

As on macOS, the server command is intended to be launched by an MCP client over stdio. If it is run manually in a shell without a client attached, it may exit when stdin closes.

Windows MCP client example:

{
  "mcpServers": {
    "fusion-studio": {
      "command": "C:\\path\\to\\fusion-studio-mcp\\.venv\\Scripts\\python.exe",
      "args": ["-m", "fusion_mcp.server"],
      "env": {
        "PYTHONPATH": "C:\\Program Files\\Blackmagic Design\\Fusion 21;C:\\path\\to\\fusion-studio-mcp\\src"
      }
    }
  }
}

Windows troubleshooting:

  • These Windows steps are documented but not yet live-validated on a clean Windows machine.

  • If python is not found, use py -3.11 or reinstall Python with PATH integration enabled.

  • If fusionscript cannot import, verify the Fusion install path and add its scripting directory to PYTHONPATH.

  • Quote paths with spaces in PowerShell and JSON; use doubled backslashes in JSON strings.

  • If connection fails, confirm Fusion Studio is open, not blocked by Windows security prompts, and has an active composition.

  • Use absolute Saver output paths in writable folders, and prefer unique output folders per render.

Quick Connection Test

  1. Open standalone Fusion Studio.

  2. Open or create a disposable composition.

  3. Run:

cd /path/to/fusion-studio-mcp
PYTHONPATH="/Applications/Blackmagic Fusion 21/Fusion.app/Contents/Libraries:src" .venv/bin/python scripts/test_fusion_connection.py

The script prints structured JSON. If Fusion is closed, it should return success: false with FUSION_NOT_RUNNING.

Read-Only Inspection Probe

Run all read-only tool functions without starting an MCP client:

cd /path/to/fusion-studio-mcp
PYTHONPATH="/Applications/Blackmagic Fusion 21/Fusion.app/Contents/Libraries:src" .venv/bin/python scripts/inspect_read_only.py

Current read-only tools:

  • fusion_get_status_tool

  • fusion_list_nodes_tool

  • fusion_get_node_tool(node_name)

  • fusion_get_selected_nodes_tool

  • fusion_summarize_comp_tool

  • fusion_get_node_input_tool(node_name, input_name)

Node list entries include:

  • Node name and Fusion tool type

  • Flow position from comp.CurrentFrame.FlowView.GetPosTable(tool) when Fusion exposes it

  • Inputs with ID, name, data type, current non-image value, connected output, and input attrs

  • Outputs with ID, name, data type, connected inputs, and output attrs

  • Key settings summary for non-image controls

Run MCP Server

After setup, run:

cd /path/to/fusion-studio-mcp
PYTHONPATH="/Applications/Blackmagic Fusion 21/Fusion.app/Contents/Libraries:src" .venv/bin/python -m fusion_mcp.server

Example MCP-style operations:

fusion_get_status_tool()
fusion_list_nodes_tool()
fusion_get_node_tool(node_name="Blur1")
fusion_get_selected_nodes_tool()
fusion_summarize_comp_tool()
fusion_select_nodes_tool(node_names=["Background1", "Transform1"])
fusion_get_node_input_tool(node_name="Transform1", input_name="Blend")
fusion_set_node_input_tool(node_name="Transform1", input_name="Blend", value=0.5)
fusion_set_node_name_tool(node_name="Transform1", new_name="Transform_Main")
fusion_set_node_position_tool(node_name="Transform_Main", x=0, y=0)
fusion_create_node_tool(tool_id="Blur", name="Blur_Main", x=1, y=0)
fusion_create_node_tool(
  tool_id="Saver",
  name="Saver_Main",
  x=2,
  y=0,
  settings={"Clip": "/tmp/example.exr"}
)
fusion_connect_nodes_tool(
  source_node="Transform_Main",
  source_output="Output",
  target_node="Blur_Main",
  target_input="Input",
  replace=false
)
fusion_get_connections_tool(node_name="Blur_Main")
fusion_disconnect_input_tool(node_name="Blur_Main", input_name="Input")
fusion_delete_node_tool(node_name="Blur_Main", confirm=true)
fusion_set_keyframe_tool(node_name="Transform_Main", input_name="Size", frame=0, value=1.0, replace=false)
fusion_get_keyframes_tool(node_name="Transform_Main", input_name="Size")
fusion_delete_keyframe_tool(node_name="Transform_Main", input_name="Size", frame=10, confirm=true)
fusion_clear_keyframes_tool(node_name="Transform_Main", input_name="Center", confirm=true)
fusion_set_expression_tool(node_name="Transform_Main", input_name="Angle", expression="time/10", replace=false)
fusion_get_expression_tool(node_name="Transform_Main", input_name="Angle")
fusion_remove_expression_tool(node_name="Transform_Main", input_name="Angle", confirm=true)
fusion_get_comp_settings_tool()
fusion_set_comp_range_tool(start_frame=1, end_frame=48)
fusion_set_current_frame_tool(frame=24)
fusion_get_current_frame_tool()
fusion_save_comp_tool(path="/tmp/example.comp")
fusion_get_comp_path_tool()
fusion_create_graph_tool(
  nodes=[
    {"id": "bg", "tool_id": "Background", "name": "BG", "x": -4, "y": 0,
     "settings": {"TopLeftRed": 0.2, "TopLeftGreen": 0.4, "TopLeftBlue": 0.8}},
    {"id": "tx", "tool_id": "Transform", "name": "TX", "x": -2, "y": 0},
    {"id": "blur", "tool_id": "Blur", "name": "Blur", "x": 0, "y": 0,
     "settings": {"XBlurSize": 3.0}},
    {"id": "saver", "tool_id": "Saver", "name": "Saver", "x": 2, "y": 0,
     "settings": {"Clip": "/tmp/example.exr"}}
  ],
  connections=[
    {"source": "bg", "target": "tx", "source_output": "Output", "target_input": "Input"},
    {"source": "tx", "target": "blur", "source_output": "Output", "target_input": "Input"},
    {"source": "blur", "target": "saver", "source_output": "Output", "target_input": "Input"}
  ],
  comp_settings={"start_frame": 1, "end_frame": 48}
)
fusion_batch_set_inputs_tool(changes=[{"node_name": "BG", "input_name": "TopLeftRed", "value": 0.5}])
fusion_batch_set_keyframes_tool(keyframes=[{"node_name": "TX", "input_name": "Size", "frame": 1, "value": 1.0}])
fusion_batch_delete_nodes_tool(node_names=["Blur"], confirm=true)
fusion_get_saver_settings_tool(node_name="Saver")
fusion_set_saver_settings_tool(node_name="Saver", settings={"Clip": "/tmp/render.exr"})
fusion_validate_render_tool(saver_node="Saver", allow_overwrite=false)
fusion_render_tool(start_frame=1, end_frame=1, saver_node="Saver", confirm=true, allow_overwrite=false)
fusion_get_render_status_tool()
fusion_abort_render_tool(confirm=true)
fusion_validate_comp_tool()
fusion_find_broken_connections_tool()
fusion_find_missing_media_tool()
fusion_get_tool_catalog_tool(search="blur")
fusion_get_tool_schema_tool(tool_id="Blur")
fusion_export_graph_tool(node_names=["BG", "TX", "Saver"])
fusion_validate_graph_request_tool(nodes=[...], connections=[...], comp_settings={...})

Example compact summary response from live empty Composition1:

{
  "success": true,
  "operation": "fusion_summarize_comp",
  "agent_summary": {
    "composition_name": "Composition1",
    "node_count": 0,
    "selected_nodes": [],
    "tool_type_counts": {},
    "plain_english": "Composition Composition1 has 0 node(s); 0 selected."
  }
}

Safe Editing Tools

Editing operations validate the active composition, node, and input before modifying anything. Writes use Fusion Lock(), StartUndo(...), EndUndo(True), and Unlock() via a defensive cleanup wrapper so failed operations do not leave an undo group open.

Implemented editing tools:

  • fusion_select_nodes_tool(node_names)

  • fusion_get_node_input_tool(node_name, input_name)

  • fusion_set_node_input_tool(node_name, input_name, value)

  • fusion_set_node_name_tool(node_name, new_name)

  • fusion_set_node_position_tool(node_name, x, y)

  • fusion_create_node_tool(tool_id, name=None, x=None, y=None)

  • fusion_connect_nodes_tool(source_node, source_output, target_node, target_input, replace=False)

  • fusion_disconnect_input_tool(node_name, input_name)

  • fusion_get_connections_tool(node_name=None)

  • fusion_delete_node_tool(node_name, confirm=False)

  • fusion_set_keyframe_tool(node_name, input_name, frame, value, replace=False)

  • fusion_get_keyframes_tool(node_name, input_name)

  • fusion_delete_keyframe_tool(node_name, input_name, frame, confirm=False)

  • fusion_clear_keyframes_tool(node_name, input_name, confirm=False)

  • fusion_set_expression_tool(node_name, input_name, expression, replace=False)

  • fusion_get_expression_tool(node_name, input_name)

  • fusion_remove_expression_tool(node_name, input_name, confirm=False)

  • fusion_get_comp_settings_tool()

  • fusion_set_comp_range_tool(start_frame, end_frame)

  • fusion_set_current_frame_tool(frame)

  • fusion_get_current_frame_tool()

  • fusion_save_comp_tool(path=None)

  • fusion_get_comp_path_tool()

  • fusion_create_graph_tool(nodes, connections, comp_settings=None)

  • fusion_batch_set_inputs_tool(changes)

  • fusion_batch_set_keyframes_tool(keyframes)

  • fusion_batch_delete_nodes_tool(node_names, confirm=False)

  • fusion_get_saver_settings_tool(node_name)

  • fusion_set_saver_settings_tool(node_name, settings)

  • fusion_validate_render_tool(saver_node=None, allow_overwrite=False)

  • fusion_render_tool(start_frame=None, end_frame=None, saver_node=None, confirm=False, allow_overwrite=False)

  • fusion_get_render_status_tool()

  • fusion_abort_render_tool(confirm=False)

  • fusion_validate_comp_tool()

  • fusion_find_broken_connections_tool()

  • fusion_find_missing_media_tool()

  • fusion_get_tool_catalog_tool(search=None)

  • fusion_get_tool_schema_tool(tool_id)

  • fusion_export_graph_tool(node_names=None)

  • fusion_validate_graph_request_tool(nodes, connections, comp_settings=None)

fusion_set_node_input_tool supports common Fusion value types:

  • finite scalar numbers

  • booleans, converted to 1 or 0 for numeric Fusion inputs

  • strings for Text inputs

  • strings for FuID inputs, validated against per-input choices when Fusion exposes them

  • points as [x, y] or {"x": x, "y": y}

  • colors as [r, g, b], [r, g, b, a], or matching dict keys when Fusion exposes a true Color input

Unsupported or ambiguous values return a structured failure and do not attempt a write. Image inputs are rejected by value-setting tools because they must be edited as connections, not scalar values.

Built-in Background color controls in Fusion Studio 21.0.2 are exposed as separate numeric channel inputs such as TopLeftRed, TopLeftGreen, TopLeftBlue, and TopLeftAlpha, each using INPID_InputControl == "ColorControl" and INPS_DataType == "Number". Live validation confirmed setting these channels with scalar floats, for example TopLeftRed = 0.25.

Example success response:

{
  "success": true,
  "operation": "fusion_set_node_input",
  "node_name": "FMC_Test_Transform",
  "input_id": "Size",
  "previous_value": 1.0,
  "requested_value": 0.8,
  "confirmed_value": 0.8,
  "summary": "Set FMC_Test_Transform.Size."
}

Example validation failure:

{
  "success": false,
  "operation": "fusion_set_node_input",
  "error_code": "UNSUPPORTED_INPUT_VALUE",
  "error_message": "Image inputs are connections, not scalar values.",
  "node_name": "FMC_Test_Transform",
  "input_id": "Input",
  "requested_value": 1
}

Connection And Node Tools

fusion_create_node_tool accepts optional settings, applied after the node exists and is validated. Setting failures produce a partial result: the created node remains in the comp, successful settings are reported, and failed settings include per-input error codes. Saver can receive its Clip path through settings={"Clip": "/path/to/output.exr"} and no longer needs the placeholder when that setting is supplied.

Connection editing is currently scoped to Image flow links. The tool layer rejects modifier, expression, mask, and scalar links with explicit socket metadata instead of pretending they are ordinary image pipes.

Safety behavior:

  • tool IDs are checked against Fusion's local registry before creation

  • MediaOut is rejected in standalone Fusion because its registry class is not creatable there

  • Saver is creatable with an explicit placeholder Clip path to avoid Fusion opening a file dialog

  • target inputs are not replaced unless replace=true

  • self-connections and obvious image-flow cycles are rejected

  • deletion requires confirm=true and only accepts one node name per call

  • all create/connect/disconnect/delete operations use Fusion undo groups

Example connection success:

{
  "success": true,
  "operation": "fusion_connect_nodes",
  "previous_state": null,
  "requested_state": {
    "source_node": "Background1",
    "source_output": "Output",
    "target_node": "Transform1",
    "target_input": "Input",
    "replace": false
  },
  "confirmed_state": {
    "node": "Background1",
    "output": "Output",
    "data_type": "Image"
  }
}

Example delete guard:

{
  "success": false,
  "operation": "fusion_delete_node",
  "error_code": "DELETE_CONFIRMATION_REQUIRED",
  "error_message": "Deletion requires confirm=true."
}

Composition And Batch Tools

Composition controls expose frame range, current frame, save path, and explicit .comp saves. Live validation confirmed fusion_set_comp_range_tool(1, 48), fusion_set_current_frame_tool(24), and fusion_save_comp_tool("/tmp/fusionmcp_batch_*.comp") in standalone Fusion Studio 21.0.2.

fusion_create_graph_tool accepts:

  • nodes: objects with id, tool_id or tool_type, optional name, optional x/y, and optional settings

  • connections: objects with graph node ids in source/target, plus source_output and target_input

  • comp_settings: currently supports start_frame/end_frame or global_start/global_end

Graph creation validates duplicate names, missing graph refs, invalid tool ids, obvious cycles, and unsupported values before or during the transaction. It creates nodes first, applies settings, then connects Image sockets. If a later step fails, it attempts to disconnect links created by that request and delete only nodes created by that request, returning status: "rolled_back" with per-item rollback results.

Batch input/keyframe/delete tools use one Fusion undo group per batch. Batch deletion requires confirm=true and only deletes explicitly listed nodes.

Render, Diagnostics, And Export

Render execution requires confirm=true. fusion_validate_render_tool checks active comp state, Saver existence/type, absolute output path, supported file extension, missing output directory, overwrite risk, valid frame range, and connected Saver image input without intentionally rendering. Existing outputs return OUTPUT_ALREADY_EXISTS unless allow_overwrite=true is explicitly supplied.

fusion_render_tool with a specific saver_node uses the canonical live-confirmed Saver transaction: it keeps the original Saver object, does not rewrite Clip, does not poll render status before rendering, calls comp.Render once with Start, End, Wait, and Tool, then confirms output files from the Saver Clip path on disk. If Fusion reports completion but no expected output file appears, the tool returns RENDER_OUTPUT_MISSING with render trace details.

Diagnostics include comp range checks, disconnected required image inputs, missing Loader paths, invalid Saver paths, expressions that evaluate to None, unresolved tool IDs, and duplicate names where detectable.

fusion_export_graph_tool emits fusionmcp.graph.v1 with exact tool IDs, input IDs, safe settings, FlowView positions, image-flow connections, and native keyframes where safely readable.

Animation And Expressions

Native keyframes use Fusion's own modifiers:

  • scalar inputs use BezierSpline

  • Point inputs use Path

  • expressions use input.SetExpression(...)

The tools distinguish static, keyframed, expression, and other modifier states. They reject silent overwrites: setting a keyframe on an expression input, setting an expression on a keyframed input, or setting a duplicate keyframe returns a structured error. Removing animation/expression data requires confirm=true.

Live-confirmed examples:

{
  "success": true,
  "operation": "fusion_get_keyframes",
  "keyframes": [
    { "frame": 0.0, "value": 1.0 },
    { "frame": 20.0, "value": 3.0 }
  ],
  "state": {
    "state_type": "keyframed",
    "modifier_type": "BezierSpline"
  }
}

Bad expressions are rejected when Fusion accepts the expression string but it evaluates to None at the current frame.

Testing

Run unit tests and lint:

cd /path/to/fusion-studio-mcp
.venv/bin/python -m pytest
.venv/bin/python -m ruff check src tests scripts

Run the opt-in live tests only against a disposable active Fusion composition:

RUN_FUSION_LIVE_TESTS=1 PYTHONPATH="/Applications/Blackmagic Fusion 21/Fusion.app/Contents/Libraries:src" .venv/bin/python -m pytest tests/test_live_editing.py tests/test_live_connections.py tests/test_live_animation.py -q

Safety

Write tools intentionally modify the active composition. Use them only on disposable or explicitly approved comps until broader production safeguards are added.

Read-only inspection intentionally does not call Output.GetValue() because that can trigger upstream rendering. Output inspection only reads output attrs and connection metadata.

Production compositions should not be used for integration testing.

Standalone Fusion Studio 21.0.2 treats MediaOut as Resolve-specific for this project. Standalone Fusion does not require a terminal node. Saver is supported as a normal standalone tool when created without AddTool defsettings and then assigned Clip after creation; no render is triggered by creation or inspection.

Render release note: live isolation on 2026-07-14 found that Saver Clip writes can read back as a valid string while the saved .comp contains a zero-span internal Clip object (Length = 0, GlobalStart/GlobalEnd = -2000000000). In that state comp.Render(...) returns success and reports the frame rendered, but no file is written. fusion_render_tool no longer rewrites Saver Clip immediately before render; validation remains side-effect-free.

Use scripts/diagnose_saver_initialization.py for live Saver initialization probes. The current raw working sequence is to create an unlocked fresh comp, lock while adding Background/Saver, set Saver Clip after creation, connect while locked, unlock, and render with Tool=saver. The harness and public fusion_render_tool now share that transaction; five consecutive public graph/validate/render cycles wrote EXR files successfully.

Troubleshooting

  • Fusion connection: make sure standalone Fusion Studio is open and has an active composition.

  • Python paths: include Fusion's bundled library path in PYTHONPATH, followed by this repo's src.

  • Saver paths: use absolute paths, supported extensions, existing output folders, and preferably unique folders per render.

  • Permissions: render output directories must be writable by the current macOS user.

  • Blocked renders: validate first with fusion_validate_render_tool; common errors are OUTPUT_DIRECTORY_MISSING, OUTPUT_ALREADY_EXISTS, SAVER_INPUT_DISCONNECTED, and INVALID_RENDER_RANGE.

  • MediaOut: standalone Fusion Studio treats MediaOut as Resolve-specific in this project; use Saver for standalone renders.

Versioning

The project uses semantic versioning. The current patch release is 0.1.1: local Fusion Studio MCP control with guarded editing, graph building, diagnostics, graph export, confirmed Saver-targeted rendering, and macOS clean-machine acceptance notes. Reserve 1.0.0 for broader production confidence across more Fusion/Resolve versions and larger real-world comps.

Install Server
F
license - not found
B
quality
A
maintenance

Maintenance

Maintainers
Response time
0dRelease cycle
2Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

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/bigsbypuglise/fusion-studio-mcp'

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