Skip to main content
Glama

millumin-mcp

An MCP server that lets Claude Code, or any MCP client, control Millumin on macOS through its OSC API.

It runs locally over stdio, started by the client. It sends OSC to Millumin and can listen for Millumin's feedback. Tested with Millumin 5.14.

Tools

Tool

Purpose

millumin_action

Run /action/<name> with optional args, e.g. launchColumn [2]

millumin_set

Set a property on a target (default selectedLayer), e.g. position/xy [0, 80]

millumin_master

Set the video, audio or dmx master, 0 to 1

millumin_send_raw

Send any OSC address

millumin_query

Send <address>/? and return the replies (needs feedback)

millumin_ping

Send /ping and return the state of every layer (needs feedback)

millumin_feedback

Read recent feedback, optionally filtered

Related MCP server: supercollider-mcp

Setup

In Millumin's Device manager (⌘K), OSC tab:

  • OSC listener on input port 5678.

  • For feedback: an OSC sender to 127.0.0.1 port 5679, with feedback on.

Build the server (Node 20 or later):

git clone https://github.com/jpkelly/millumin-mcp.git
cd millumin-mcp
npm install
npm run build

Add it to your MCP client:

{
  "mcpServers": {
    "millumin": {
      "command": "node",
      "args": ["/path/to/millumin-mcp/dist/server.js"],
      "env": { "MILLUMIN_FEEDBACK_PORT": "5679" }
    }
  }
}

Variable

Default

MILLUMIN_HOST

127.0.0.1

Where Millumin runs

MILLUMIN_PORT

5678

Millumin's OSC listener port

MILLUMIN_FEEDBACK_PORT

unset

Port to receive feedback on; unset turns feedback off

MILLUMIN_ALLOW_DESTRUCTIVE

unset

1 allows /action/quit and /action/saveProject, which are refused otherwise

Notes

  • Millumin's OSC API can't create layers, canvases, outputs or routings. Make those in Millumin.

  • selectedLayer follows the selection in Millumin's interface. Target index:N when the selection may change.

  • Launching a column that is already playing doesn't restart it. goToTime [0] restarts all media together.

  • Feedback gives layer names in lowercase.

Tests

npm test

Runs against a fake Millumin on a loopback port, never a real one.

License

MIT

Available Tools

7 tools
millumin_actionB

Run a Millumin action, e.g. launchColumn [index or name], stopColumn, launchNextColumn, playOrPause, goToTime [seconds], selectLayer [index or name], displayTestCard, hideTestCard.

NameRequiredDescriptionDefault
argsNoAction arguments
nameYesAction name without the /action/ prefix, e.g. launchColumn

TDQS

B3.1/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full behavioral burden. It lists action names but does not disclose side effects, permissions, reversibility, error behavior, or whether actions are synchronous, which is a significant gap for an action-execution tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single front-loaded sentence with no filler, and the examples earn their place by illustrating valid action names and argument forms. The dense list format is efficient, though it could be slightly more structured.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a two-parameter tool with full schema coverage and no output schema, the description is adequate to call common actions. However, the absence of annotations leaves behavioral details such as side effects, permissions, and error handling undocumented, and sibling differentiation is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds useful meaning by showing example action names and their expected arguments, such as launchColumn [index or name] and goToTime [seconds]. This helps the agent understand how the generic 'args' array is used in practice.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: 'Run a Millumin action', and gives concrete action names such as launchColumn and goToTime. It is clear what the tool does, though it does not explicitly distinguish itself from siblings like millumin_send_raw or millumin_set.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The examples imply that this tool runs named Millumin actions, but there is no explicit guidance on when to use it versus alternatives such as millumin_set, millumin_send_raw, or millumin_query. No exclusions or preconditions are stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

millumin_feedbackA

Return recent feedback messages from Millumin (addresses start with /millumin), optionally filtered by a case-insensitive substring such as "launchedColumn" or "layer:Intro".

NameRequiredDescriptionDefault
patternNo
sinceSecondsNoOnly messages from the last N seconds

TDQS

A3.5/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden: it does disclose that matching is case-insensitive and that addresses are namespaced under /millumin, which is genuine added context. However it omits whether reads are non-destructive, whether messages accumulate or are consumed, ordering, and any result-count limit — all relevant for a feedback-buffer read.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

One sentence, front-loaded with the action and resource, with the optional filter trailing. The parenthetical examples are useful rather than padding; no wasted prose.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema and no annotations, the description should say something about what a returned message looks like (timestamp, address, value) or how many come back. It covers input-side filtering adequately but leaves the response shape entirely unspecified.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 50%, and the description compensates for the undocumented `pattern` parameter by specifying case-insensitive substring semantics plus two concrete example values. `sinceSeconds` is already documented in the schema, so the remaining gap is minor.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource (return recent feedback messages from Millumin) and narrows scope to /millumin-prefixed addresses. It does not distinguish itself from the sibling millumin_query, which plausibly also reads Millumin state, so an agent may hesitate between the two.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied by the filtering examples ("launchedColumn", "layer:Intro"), which show the kinds of things to search for, but there is no explicit statement of when to prefer this over millumin_query or millumin_ping, nor any exclusion guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

millumin_masterB

Set a master level: video, audio, or dmx. Value is normalized 0..1.

NameRequiredDescriptionDefault
valueYes
channelYes

TDQS

B3.1/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden. It does not say whether the master applies live to output, whether setting is immediate, what happens to previously set levels, or what is returned - significant gaps for an unannotated mutation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences, zero filler, and the action and channel set are front-loaded. Nothing needs to be trimmed.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple two-parameter mutation with no annotations and no output schema, the description is minimally viable: the inputs are covered, but behavior of the write (effect timing, scope across channels, error conditions) is absent.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, but the description does cover both parameters: the channel enum values (video/audio/dmx) are echoed and 'normalized 0..1' clarifies that 1 means full level rather than an arbitrary float range. That is modest added meaning; the schema already provides the min/max bounds.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (Set) and a specific resource (a master level) with its three channels enumerated. It is clear what the tool does, but it never contrasts with the very generically named sibling millumin_set, so an agent could plausibly confuse the two.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no explicit guidance on when to use this tool versus millumin_set or millumin_action, no prerequisites, and no note on when not to use it. The only usage signal is the implicit 'you want to set a master level'.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

millumin_pingB

Send /ping and return the layer and board state Millumin reports back. Requires MILLUMIN_FEEDBACK_PORT and Millumin's OSC "API feedback" enabled and pointed at that port.

NameRequiredDescriptionDefault
waitMsNo

TDQS

B3.3/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden, and it does disclose a non-obvious external dependency (env var plus a setting inside Millumin) that an agent could not infer from the schema. It stops short of describing failure behavior — what happens if no feedback arrives, whether the call errors or returns empty — which matters for a network/OSC round-trip tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, zero filler, with the action and its return value front-loaded and the prerequisite following. Every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

There is no output schema, so the description must carry return semantics; it names the returned data (layer and board state) but not its shape. Combined with the undocumented waitMs and the absence of timeout/failure behavior, a network-dependent tool is left partially specified.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0% and the single parameter waitMs (integer, default 1000, 100–10000) is never mentioned in the description. Its obvious meaning — how long to wait for the feedback reply before giving up — is exactly the kind of semantics the description should supply and does not.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource — send /ping and return layer and board state — which is concrete and actionable. It does not, however, distinguish itself from siblings like millumin_feedback or millumin_query, which plausibly return overlapping state, so an agent cannot route between them from the description alone.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives a hard prerequisite (MILLUMIN_FEEDBACK_PORT set, Millumin's OSC 'API feedback' enabled and pointed at that port), which implicitly frames this as a connectivity/health check. But it never says when to prefer this over millumin_feedback or millumin_query, nor what to do if the precondition is unmet.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

millumin_queryA

Ask Millumin for the current value of one property by sending address + "/?", then return any feedback that came back. Example address: /layer:Intro/opacity.

NameRequiredDescriptionDefault
waitMsNo
addressYes

TDQS

A3.6/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden, and it does disclose meaningful behavior: it appends "/?" to the address and returns 'any feedback that came back,' hinting the response may be empty. It does not say what happens on timeout, whether feedback is guaranteed, or what a failed query returns — gaps that matter for a read tool with no annotation safety net.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, front-loaded with the action and followed by the concrete wire-protocol example. No filler, no repetition of schema constraints.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple one-address read with no output schema, the description gives enough to construct a call: the address format, the appended suffix, and the shape of the response. The main omission is timeout/empty-response behavior tied to `waitMs`, which an agent would need to interpret a blank result.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, so the description must compensate. It does well on the required `address` param by giving the format convention and a concrete example (`/layer:Intro/opacity`), but `waitMs` (100–5000, default 500) is never mentioned, leaving a timing control that directly affects whether feedback is captured completely undocumented.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource: read the current value of one property from Millumin. The protocol detail (address + "/?") and the example address make the operation unambiguous, though it never names the read-vs-write boundary against siblings like millumin_set or millumin_feedback.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is only implied by the word 'query' — an agent can infer this is the read path while millumin_set is the write path, but the description never says when to pick this over millumin_feedback or millumin_send_raw, nor any prerequisites.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

millumin_send_rawA

Send an arbitrary OSC message to Millumin. Use only when no typed tool fits. Destructive addresses (/action/quit, /action/saveProject) are refused unless the server was started with MILLUMIN_ALLOW_DESTRUCTIVE=1.

NameRequiredDescriptionDefault
argsNo
addressYesOSC address, e.g. /selectedLayer/opacity

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the safety burden and discloses an important guardrail: destructive OSC addresses are refused unless MILLUMIN_ALLOW_DESTRUCTIVE=1. It does not fully describe side effects of non-destructive messages, response behavior, or error handling.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is three tight sentences with purpose, usage constraint, and safety behavior front-loaded. There is no redundant or filler text.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

It covers the critical escape-hatch usage rule and destructive-address guard, which are the main risks. However, with no annotations and no output schema, it leaves gaps around args semantics, return values, and error behavior.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is only 50%, and the description does not explain the args parameter or how values map to OSC arguments. The address parameter is already documented in the schema, so the description adds little parameter meaning beyond the structured fields.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: send an arbitrary OSC message to Millumin. It also distinguishes this escape-hatch tool from the typed tools by saying to use it only when no typed tool fits.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives a clear last-resort rule: use only when no typed tool fits. It also names destructive addresses that are blocked unless an environment flag is set, though it does not explicitly name the alternative typed sibling tools.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

millumin_setB

Set a property on a target. Target defaults to selectedLayer; other forms are layer:, light:, index:, or an element name. Property examples: opacity, position/x, position/xy, rotation, scale, intensity, media/speed, media/normalizedTime.

NameRequiredDescriptionDefault
valueYesValue; arrays are sent as multiple args
targetNoTarget element, e.g. selectedLayer or layer:IntroselectedLayer
propertyYesProperty path, e.g. opacity or position/xy

TDQS

B3.4/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description must carry the behavioral burden. 'Set' implies mutation and the default target is disclosed, but permissions, side effects, reversibility, error behavior, and return behavior are all omitted.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is compact and front-loaded: the core operation comes first, followed by target syntax and property examples. Every clause contributes directly to invocation.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

It covers target and property syntax well, and the schema fully documents the value parameter. But with no annotations and no output schema, the description leaves mutation side effects, error behavior, and sibling selection guidance unaddressed.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3. The description earns a bump by adding target forms beyond the schema example ('light:<name>', 'index:<n>', element name) and extra property paths such as 'position/x' and 'media/speed'.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: 'Set a property on a target.' It adds property examples that clarify the kind of operation, but it never differentiates this tool from siblings such as millumin_action or millumin_send_raw.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied by the operation name, and the target-default sentence helps invocation. However, the description never states when to choose this over millumin_action, millumin_send_raw, or other siblings, nor does it give prerequisites or exclusions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

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

  1. 7 tool updatesv0.1.0
    • First observedmillumin_action
    • First observedmillumin_feedback
    • First observedmillumin_master
    • First observedmillumin_ping
    • First observedmillumin_query
    • First observedmillumin_send_raw
    • First observedmillumin_set

TDQS

A3.5/5.0

Scored across 7 tools

Disambiguation4/5

The typed tools separate command execution (millumin_action), property setting (millumin_set), and master-level setting (millumin_master) clearly. millumin_query, millumin_feedback, and millumin_ping all expose feedback/state but with distinguishable purposes, while millumin_send_raw overlaps everything as a fallback, keeping this from a perfect score.

Naming Consistency3/5

All names share the millumin_ prefix and snake_case, which aids readability. However, suffixes mix nouns and verbs (action, master, feedback, ping, query vs set, send_raw) rather than following a single predictable verb_noun convention.

Tool Count5/5

Seven tools is well within the appropriate range for an OSC control bridge. Each tool has a distinct role: typed control, master control, raw fallback, and introspection.

Completeness4/5

The surface covers core control and introspection: actions, property setting, master levels, targeted queries, recent feedback, ping state, and raw OSC as an escape hatch. Typed discovery/listing of layers, columns, media, or available properties is not provided, though raw OSC can fill those gaps.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers