Skip to main content
Glama

nuke-mcp

An MCP server for Foundry Nuke. It lets any MCP-capable agent (Claude, ChatGPT / Codex, Gemini and others) read and edit Nuke scripts, render Write nodes and look at the output of any node. It works two ways, chosen per call:

  • live: the Nuke you have open. The agent sees and edits the same script as you, and every change is one undo step.

  • headless: a fresh nuke -t process on a .nk file. Nothing has to be open; it uses one Nuke licence while it runs.

Agent (Claude / Codex / Gemini)
        │  MCP (stdio)
        ▼
  nuke-mcp  (this package, Python ≥ 3.11, outside Nuke)
        │                                   │
        │ live: JSON over TCP               │ headless: Nuke -t headless_runner.py
        │ 127.0.0.1:7393 + shared token     │ (job and result as JSON files)
        ▼                                   ▼
  nuke_mcp_bridge plugin (inside Nuke,   nuke_mcp_bridge.commands
  on Nuke's main thread)                 (the same code, the same commands)

Both backends run the same commands, so every tool behaves the same live and headless.

Requirements

  • Nuke 16 or 17 (tested on Nuke 17.1v2, macOS).

  • uv (curl -LsSf https://astral.sh/uv/install.sh | sh).

Related MCP server: nuke-mcp

Installation

1. Nuke plugin (once per machine)

Only needed for the live mode. Headless works without it.

uvx --from git+https://github.com/hramirezedc/nuke-mcp nuke-mcp install-plugin

This copies the nuke_mcp_bridge package into ~/.nuke/, adds a marked block to ~/.nuke/init.py (your own lines are kept) and creates the shared token in ~/.nuke_mcp/token. Restart Nuke, then check both backends:

uvx --from git+https://github.com/hramirezedc/nuke-mcp nuke-mcp status

The listener starts in GUI sessions only; nuke -t never opens a socket. To skip it for one session, launch Nuke with NUKE_MCP_DISABLE=1. To remove it: nuke-mcp uninstall-plugin.

2. Register the server with your agent

In every case the command is uvx --from git+https://github.com/hramirezedc/nuke-mcp nuke-mcp. Desktop apps don't always inherit your shell PATH: if they can't find uvx, use its full path (which uvx).

Claude Desktop: in ~/Library/Application Support/Claude/claude_desktop_config.json

{
  "mcpServers": {
    "nuke": {
      "command": "/Users/YOU/.local/bin/uvx",
      "args": ["--from", "git+https://github.com/hramirezedc/nuke-mcp", "nuke-mcp"]
    }
  }
}

Claude Code

claude mcp add nuke -- uvx --from git+https://github.com/hramirezedc/nuke-mcp nuke-mcp

OpenAI Codex CLI: in ~/.codex/config.toml

[mcp_servers.nuke]
command = "uvx"
args = ["--from", "git+https://github.com/hramirezedc/nuke-mcp", "nuke-mcp"]

Gemini CLI: in ~/.gemini/settings.json

{
  "mcpServers": {
    "nuke": {
      "command": "uvx",
      "args": ["--from", "git+https://github.com/hramirezedc/nuke-mcp", "nuke-mcp"]
    }
  }
}

Restart the app after editing its configuration.

Live or headless?

Every tool that works on a script takes script (a .nk path) and mode:

mode

What happens

auto (default)

Live if Nuke is open and has script open (or no script was given). Otherwise headless on script.

live

Live only. Error if Nuke is not open, or has another script open.

headless

Always a new nuke -t process on script.

  • Headless edits are saved back to the file, and the previous version is kept as <name>.nk.bak.

  • render runs headless by default, so the Nuke window never freezes. With no script it renders a snapshot of the live script, including unsaved changes, and deletes the snapshot afterwards. mode="live" renders inside the open Nuke instead. Either way it checks that every expected frame exists on disk.

  • open_script, save_script, undo, redo, get_selection and set_selection only exist in a live session.

  • Apart from render, a headless run does not see the unsaved changes of your open session.

Headless uses the newest Nuke it finds in /Applications. Choose a version with NUKE_MCP_NUKE_VERSION=17.0, or an executable with NUKE_MCP_EXE.

Tools

Area

Tools

Application and script

get_app_info, get_script_info, open_script, save_script, undo, redo, execute_python

Nodes

list_nodes, get_node, create_node, set_knobs, connect_node, delete_nodes, get_selection, set_selection

Output

render, preview_frame (returns an image of any node at any frame)

Live changes are one undo step each, cancelled again if the command fails half way. delete_nodes deletes nothing if one name is wrong. Tools that delete or overwrite carry destructiveHint, so agents ask before using them.

Knob values: numbers, strings and booleans; lists for multi-value knobs ([r, g, b, a]); "=expr" or {"expression": "…"} for expressions; {"keyframes": {"1": 0, "24": 1}} for animation; {"script": "…"} for Nuke's own text form. A Read's file accepts "name.####.exr 1001-1100".

Configuration

Variable

Used by

Default

NUKE_MCP_PORT / NUKE_MCP_HOST

Nuke and server

7393 / 127.0.0.1

NUKE_MCP_TOKEN

Nuke and server

contents of ~/.nuke_mcp/token

NUKE_MCP_HOME

Nuke and server

~/.nuke_mcp

NUKE_MCP_DISABLE

Nuke

unset

NUKE_MCP_EXE / NUKE_MCP_NUKE_VERSION

server (headless)

newest installed Nuke

The default port differs from hiero-mcp (7392), so both can run at once. Only one Nuke GUI can hold the port: a second one prints a message and runs without the listener.

Development

uv sync
uv run pytest                          # offline tests, no Nuke needed
uv run python scripts/live_check.py    # with Nuke open: runs every tool in a throw-away script

The offline tests run the real listener, client, MCP server and headless runner against tests/fake_nuke.py, a small stand-in for the nuke module (and a fake Nuke -t executable). The live check needs Nuke open with no unsaved changes: it opens a script in a temporary folder and works only there.

src/nuke_mcp/server.py defines the MCP tools. src/nuke_mcp/nuke_plugin/nuke_mcp_bridge/commands.py implements them with the Nuke API. Each tool has a command with the same name and parameters, and the tests check that they stay in sync. After changing the plugin, run nuke-mcp install-plugin and restart Nuke.

License

Freeware by Toolbox Design, all rights reserved: free to use, including commercially, but not to modify, redistribute or sell. See LICENSE. Foundry and Nuke are trademarks of their respective owners; this project is not affiliated with Foundry.

Available Tools

17 tools
connect_nodeA

Connect source to input number input of node (0 is the main input). Leave source empty to disconnect.

Inputs: node (required), mode, input, script, +1 more. Returns: object

create_nodeA

Create a node (e.g. "Blur", "Grade", "Read", "Write") with optional name, knob values and input node names.

Without `position` the node is placed under its first input. Headless runs save the script afterwards.

Inputs: node_class (required), mode, name, knobs, +3 more. Returns: object

delete_nodesA
Destructive

Delete nodes by name. Nothing is deleted if one of the names does not exist.

Inputs: nodes (required), mode, script. Returns: object

execute_pythonA
Destructive

Run Python in Nuke for anything the other tools do not cover.

`nuke` is pre-imported. Assign to a variable named `result` to return a JSON-serialisable value;
stdout, stderr and any traceback are returned too. Headless runs only keep changes to the script when `save` is true.

Inputs: code (required), mode, save, script. Returns: object

get_app_infoA
Read-only

Which Nuke backends are available: the live GUI session (version, open script) and the installed executables used for headless runs.

Inputs: no named parameters. Returns: object

get_nodeC
Read-only

One node's inputs, dependents and knobs. By default only knobs that differ from their default are listed.

Inputs: node (required), mode, script, all_knobs. Returns: object

get_script_infoC
Read-only

Frame range, fps, format, colour management, node counts by class, and the names of Read and Write nodes.

Inputs: mode, script. Returns: object

get_selectionB
Read-only

Names of the nodes selected in the live Nuke session.

Inputs: no named parameters. Returns: object

list_nodesB
Read-only

Nodes with class, position, inputs and disabled flag. Filter by class ("Blur"), selection, text in the name, or look inside a Group node by name.

Inputs: mode, group, limit, script, +3 more. Returns: object

open_scriptA
Destructive

Open a .nk script in the live Nuke session. Refuses if the open script has unsaved changes unless discard_changes is true.

Inputs: path (required), discard_changes. Returns: object

preview_frameB
Read-only

Look at the output of any node: renders one frame to an image and returns it.

Uses a temporary Write node (removed afterwards). `max_size` is the longest-side width in pixels the image is scaled down to.

Inputs: node (required), mode, frame, format, +2 more.

redoA

Redo the last undone action in the live Nuke session.

Inputs: no named parameters. Returns: object

renderA

Render a Write node and check that the expected frames exist on disk.

Runs headless so the Nuke interface stays usable: with no `script` it renders a snapshot of the live
script (including unsaved changes). With mode="live" it renders inside the open Nuke and blocks its interface.
Frame range defaults to the script's.

Inputs: write_node (required), last, mode, step, +3 more. Returns: object

save_scriptA

Save the live script, or save it to a new .nk path ("save as") when path is given.

Inputs: path. Returns: object

set_knobsC

Set one or more knobs on a node. Returns the values they have afterwards.

Inputs: node (required), knobs (required), mode, script. Returns: object

set_selectionA

Select nodes in the live Nuke session (replaces the selection unless add is true).

Inputs: nodes (required), add. Returns: object

undoA

Undo the last action in the live Nuke session.

Inputs: no named parameters. Returns: object

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    B3.4/5.0

    Scored across 17 tools

    Disambiguation4/5

    Each tool maps to a distinct resource+action: node listing/inspection (list_nodes vs get_node) is differentiated by the knobs/dependents detail, and app vs script info are clearly scoped. The only real overlap is execute_python acting as a superset of every other tool, plus mild adjacency between set_knobs and create_node's knob arguments, but these are conventional escape hatches rather than true ambiguity.

    Naming Consistency4/5

    The dominant pattern is verb_noun (get_app_info, list_nodes, create_node, set_knobs, delete_nodes, set_selection), applied consistently with correct singular/plural semantics. Deviations are the bare verbs undo/redo and the noun-ish render/preview_frame, which are idiomatic for a DCC app and remain readable.

    Tool Count4/5

    17 tools is slightly above the comfortable band but each earns its place across session control, node graph editing, selection, and rendering. Nothing looks like a redundant wrapper, though consolidation (e.g. selection get/set) could trim it a little.

    Completeness4/5

    Coverage is strong: script lifecycle (open/save), undo/redo, node CRUD, knob edits, graph wiring, selection, render verification, and a Python escape hatch for anything missing. Minor gaps remain around creating a new script from scratch, cloning/grouping nodes, and closing/reverting the session, all of which execute_python can work around.

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      B
      quality
      D
      maintenance
      A production-grade MCP server for Foundry Nuke that enables AI assistants to understand and manipulate compositing environments, including AOVs, deep workflows, distortion, tracking, OCIO/ACEScct, and CopyCat ML.
      45
      MIT
    • A
      license
      Not graded
      quality
      C
      maintenance
      Enables language models to inspect the current Houdini scene, create and modify nodes, and run VEX/Python code in the running Houdini session via MCP.
      1
      MIT