About Nova Control MCP Server
Nova Control MCP Server is an MCP server in the Browser category: mCP server for controlling a NOVA DIY Artificial Intelligence Robot by Creoqode.
Install
claude mcp add nova-control-mcp-server -- npx -y nova-control-mcp-servernpx -y nova-control-mcp-serverThis server has no ConduID identity, so agent calls to it are not receipted. Pin the version you install and review the source before granting it credentials.
Tools (12)
disconnect—
Parameters not published.
get_state—
Parameters not published.
home`within_ms?`
Parameters not published.
lift_to`angle: number`; `within_ms?`
Parameters not published.
move`shift_to?`, `roll_to?`, `pitch_to?`, `rotate_to?`, `lift_to?` (at least one required); `within_ms?`
Parameters not published.
move_to`within_ms: number` (required, > 0); `s1?`, `s2?`, `s3?`, `s4?`, `s5?`
Parameters not published.
pitch_to`angle: number`; `within_ms?`
Parameters not published.
roll_to`angle: number`; `within_ms?`
Parameters not published.
rotate_to`angle: number`; `within_ms?`
Parameters not published.
run_script`script: string`
Parameters not published.
shift_to`angle: number`; `within_ms?`
Parameters not published.
wait`ms: number`
Parameters not published.
Ask AI
Ask AI about Nova Control MCP Server
Powered by Claude · Grounded in docs
Security checks
- ✓README presentThe repository ships documentation.
5 checks have not been run yet.
README
nova-control
Control a Creoqode Nova DIY AI Robot from a browser, Node.js, the command line, or an AI assistant — over USB serial.
Overview
This monorepo contains four npm packages and one Arduino sketch:
| package | target | what it does |
|---|---|---|
nova-control-browser |
browser | Web Serial API — Chrome / Edge 89+ |
nova-control-node |
Node.js | serialport package — any OS |
nova-control-command |
CLI | one-shot commands, REPL, script files |
nova-control-mcp-server |
AI assistant | MCP server for Claude / other LLM clients |
The sketch Nova_SerialController.ino must be uploaded to the robot's Arduino (Creoqode Mini Mega / Arduino Mega-compatible) before using any of the packages.
Arduino sketch
Nova_SerialController.ino — upload this once to the robot.
- baud rate: 9600, 8N1
- protocol: 5-byte direct servo control packet
- servo pin assignments: s1→32, s2→34, s3→36, s4→38, s5→40
- safe ranges enforced on-board and in the JS packages:
- s1 (head shift): 45–135°
- s2 (head roll): 10–170°
- s3 (head pitch): 40–150°
- s4 (body rotation): 30–180°
- s5 (head lift): 20–150°
nova-control-browser
ESM module for controlling Nova from a browser via the Web Serial API (Chrome / Edge 89+).
import { openNova } from 'nova-control-browser'
// must be called from a user gesture (e.g. a button click)
button.addEventListener('click', async () => {
const Nova = await openNova() // shows browser port picker
await Nova.home()
await Nova.rotateBodyTo(120)
console.log(Nova.State) // { s1:90, s2:90, s3:110, s4:120, s5:95 }
Nova.destroy()
})
Pass an existing SerialPort object (extends EventTarget) to skip the port picker:
const Nova = await openNova(existingPort)
Coalescing state setter
Nova.State = { s4:120 } // queues a state update
Nova.State = { s1:100 } // replaces queue; starts fresh from last-sent state
await Nova.sendServoState() // sends one 5-byte packet: s1=100, s4=90 (last-sent)
Named methods accumulate on top of whatever is already pending:
Nova.shiftHeadTo(120) // pending: { ...last, s1:120 }
Nova.rollHeadTo(60) // pending: { ...last, s1:120, s2:60 }
await Nova.sendServoState() // one packet with both changes
nova-control-node
ESM module for controlling Nova from Node.js via the serialport package.
import { openNova } from 'nova-control-node'
const Nova = await openNova('/dev/ttyACM0') // or 'COM3' on Windows
await Nova.home()
await Nova.pitchHeadTo(130)
console.log(Nova.State)
Nova.destroy()
An optional second argument overrides the default baud rate:
const Nova = await openNova('/dev/ttyACM0', 115200)
The API is otherwise identical to nova-control-browser.
Exported API (both browser and node)
| symbol | type | description |
|---|---|---|
BaudRate |
number |
9600 |
HomePosition |
ServoState |
{ s1:90, s2:90, s3:110, s4:90, s5:95 } |
SafeRange |
Record<ServoKey, [number, number]> |
per-servo safe angle ranges |
buildDirectPacket(state) |
Uint8Array |
builds a 5-byte direct servo control packet |
openNova(...) |
Promise<NovaController> |
opens the port and returns a controller |
runScript(Nova,Script) |
Promise<void> |
executes a multi-line movement script against an open controller |
NovaController interface
| method / accessor | description |
|---|---|
home(withinMS?) |
moves all servos to HomePosition |
shiftHeadTo(angle, withinMS?) |
s1 — head forward / back |
rollHeadTo(angle, withinMS?) |
s2 — head CW / CCW |
pitchHeadTo(angle, withinMS?) |
s3 — head up / down |
rotateBodyTo(angle, withinMS?) |
s4 — body Z-axis rotation |
moveTo(Target, withinMS?) |
moves the servos in Target to their angles; with withinMS, uses a trapezoidal ramp profile |
liftHeadTo(angle, withinMS?) |
s5 — secondary head axis (20–150°) |
get State |
returns a deep copy of the current or pending state |
set State(update) |
replaces the pending update; starts fresh from last-sent |
sendServoState() |
flushes the pending state as a single packet |
destroy() |
closes the serial port |
nova-control-command
CLI tool for sending commands to Nova from a terminal.
Install globally and use the nova-control binary:
npm install -g nova-control-command
nova-control --port /dev/ttyACM0 home
nova-control --port /dev/ttyACM0 shift-to 120
nova-control --port /dev/ttyACM0 move --shift-to 120 --rotate-to 45
nova-control --port /dev/ttyACM0 shell # interactive REPL
nova-control --port /dev/ttyACM0 --script run.nova
Or run without installing via npx:
npx nova-control-command --port /dev/ttyACM0 home
npx nova-control-command --port /dev/ttyACM0 shell
Global options
| option | default | description |
|---|---|---|
--port <path> |
(required) | serial port, e.g. /dev/ttyACM0 or COM3 |
--baud <rate> |
9600 |
baud rate |
--on-error <mode> |
stop |
script error handling: stop, continue, ask |
--script <file> |
— | run commands from a file (- for stdin) |
Commands
| command | arguments / options | description |
|---|---|---|
home |
[--within-ms <ms>] |
send all servos to home positions |
shift-to <angle> |
[--within-ms <ms>] |
s1: head forward / back |
roll-to <angle> |
[--within-ms <ms>] |
s2: head CW / CCW |
pitch-to <angle> |
[--within-ms <ms>] |
s3: head up / down |
rotate-to <angle> |
[--within-ms <ms>] |
s4: body Z-axis |
lift-to <angle> |
[--within-ms <ms>] |
s5: secondary head axis |
move |
--shift-to, --roll-to, --pitch-to, --rotate-to, --lift-to (at least one required); [--within-ms <ms>] |
set one or more servos in one packet |
wait <ms> |
— | pause for the given number of milliseconds |
state |
— | print the current servo state as JSON |
shell |
— | start an interactive REPL |
Script file format
One command per line; # begins a comment; blank lines are ignored:
# move to a position, pause, then go home
shift-to 120 --within-ms 1000
wait 500
home --within-ms 500
nova-control-mcp-server
MCP (Model Context Protocol) server that exposes Nova as tools for an AI assistant (Claude, etc.).
npx nova-control-mcp-server --port /dev/ttyACM0
Or add to your MCP client configuration (e.g. Claude Desktop claude_desktop_config.json):
{
"mcpServers": {
"nova": {
"command": "npx",
"args": ["nova-control-mcp-server", "--port", "/dev/ttyACM0"]
}
}
}
MCP tools
All movement tools accept an optional within_ms parameter for smooth trapezoidal motion (ramp-up → constant speed → ramp-down). Without it, servos move at constant maximum speed.
| tool | arguments | description |
|---|---|---|
home |
within_ms? |
move all servos to home positions |
shift_to |
angle: number; within_ms? |
s1: head forward / back |
roll_to |
angle: number; within_ms? |
s2: head CW / CCW |
pitch_to |
angle: number; within_ms? |
s3: head up / down |
rotate_to |
angle: number; within_ms? |
s4: body Z-axis rotation |
lift_to |
angle: number; within_ms? |
s5: secondary head axis (20–150°) |
move |
shift_to?, roll_to?, pitch_to?, rotate_to?, lift_to? (at least one required); within_ms? |
set one or more servos atomically |
move_to |
within_ms: number (required, > 0); s1?, s2?, s3?, s4?, s5? |
move one or more servos smoothly to target positions |
wait |
ms: number |
pause for the given number of milliseconds |
get_state |
— | return the current servo state as JSON |
run_script |
script: string |
execute a multi-line movement script (one command per line; blank lines and #-comments ignored) |
disconnect |
— | close the serial connection; reopens automatically on the next command |
CLI options
| option | default | description |
|---|---|---|
--port <path> |
(required) | serial port |
--baud <rate> |
9600 |
baud rate |
Protocol
Each packet is exactly 5 bytes, no framing byte:
- byte order:
[s4, s3, s2, s1, s5] - each byte is a servo angle in degrees, clamped to the servo's safe range
- fractional values are rounded to the nearest integer before transmission
- baud rate: 9600, 8N1
Repository structure
nova-control/
├── Nova_SerialController.ino Arduino sketch (upload once)
├── packages/
│ ├── nova-control-browser/ Web Serial API module
│ ├── nova-control-node/ Node.js serialport module
│ ├── nova-control-command/ CLI tool
│ └── nova-control-mcp-server/ MCP server
└── package.json npm workspace root
Development
# install all workspace dependencies
npm install
# build all packages
npm run build
# run all test suites
npm run test:run
Each package has its own vitest.config.ts, TestPlan.md, and TestCases.md.
Build order
nova-control-command and nova-control-mcp-server both depend on the built output of nova-control-node. The root build script therefore runs the packages in two sequential tiers:
nova-control-browserandnova-control-node(no intra-workspace dependencies)nova-control-commandandnova-control-mcp-server(depend onnova-control-node)
This ordering is encoded directly in the root build script, so npm run build always works correctly even after a full clean.
License
MIT © Andreas Rozek
README copy captured when this server was indexed; it may lag the repository. The original is authoritative.