Moonraker MCP server for E3CNC UI — exposes printer state, G-code, history, and system info as MCP tools
Project description
Moonraker MCP
A Moonraker component and MCP (Model Context Protocol) server for the E3CNC UI project.
What's inside
This package contains two things:
| Component | Purpose |
|---|---|
CNC agent (cnc_agent.py) |
Moonraker component registered under [cnc_agent] — owns spindle, coolant, units, WCS, jog, and settings state. Vended into moonraker/moonraker/components/ during install. |
MCP server (mcp_server.py) |
A standalone stdio-based MCP server that exposes Moonraker's API as MCP tools for AI agents. |
CNC Agent
The CNC agent owns CNC-specific state that Klipper does not model:
- spindle state and control (
state,rpm,override) - coolant state and control (
flood,mist) - units tracking (
G20/G21) - active work coordinate system (
G54..G59,G53) and per-WCS offsets - safe jog / set-zero / WCS-select command endpoints
- CNC dashboard settings persistence (separate from Mainsail's settings)
- machine profile loading for capability/safety/frontend feature gating
It registers HTTP endpoints under /server/cnc/*:
| Endpoint | Methods | Description |
|---|---|---|
/server/cnc/state |
GET | Full agent state snapshot |
/server/cnc/spindle |
GET, POST | Read or control spindle (M3/M4/M5) |
/server/cnc/coolant |
GET, POST | Read or control coolant (M7/M8/M9) |
/server/cnc/units |
GET, POST | Read or set units (G20/G21) |
/server/cnc/wcs |
GET | Query WCS offsets from Klipper |
/server/cnc/wcs/select |
POST | Select active WCS (G54–G59) |
/server/cnc/wcs/set-zero |
POST | Set work zero at current position (G10 L20) |
/server/cnc/jog |
POST | Execute a guarded jog move |
/server/cnc/settings |
GET, POST | Read or persist CNC dashboard settings |
Read-only Klipper machine state is not re-exposed — the frontend reads it directly from Mainsail's existing websocket store subscription.
MCP Server
The MCP server connects to a running Moonraker instance and exposes 13 tools that AI agents can call.
13 Exposed MCP Tools
| Tool | Moonraker Endpoint | What it does |
|---|---|---|
moonraker_server_info |
GET /server/info |
Moonraker version, loaded components |
moonraker_server_config |
GET /server/config |
Parsed moonraker.conf |
moonraker_printer_info |
GET /printer/info |
Klippy host info |
moonraker_printer_objects_list |
GET /printer/objects/list |
Loaded Klipper objects |
moonraker_query_printer_objects |
POST /printer/objects/query |
Query printer object state |
moonraker_gcode_help |
GET /printer/gcode/help |
Supported G-code commands |
moonraker_send_gcode |
POST /printer/gcode/script |
Send G-code to Klipper |
moonraker_job_queue_status |
GET /server/job_queue/status |
Job queue state |
moonraker_history_list |
GET /server/history/list |
Print history (filterable) |
moonraker_webcams_list |
GET /server/webcams/list |
Configured webcams |
moonraker_system_info |
GET /machine/system_info |
Host OS and service info |
moonraker_proc_stats |
GET /machine/proc_stats |
Process statistics |
moonraker_request |
Generic | Raw request to any Moonraker endpoint |
Running the MCP server
Option A — install from PyPI (recommended):
pip install moonraker-mcp
moonraker-mcp
Option B — install from source:
cd E3CNC/moonraker-mcp
pip install -e .
moonraker-mcp
Option C — run directly (no install):
cd E3CNC/moonraker-mcp
PYTHONPATH=src python -m moonraker_mcp.mcp_server
Environment variables
| Env Var | Default | Purpose |
|---|---|---|
MOONRAKER_URL |
http://127.0.0.1:7125 |
Moonraker API base URL |
MOONRAKER_API_KEY |
(none) | API key if Moonraker auth is configured |
MOONRAKER_TIMEOUT |
15 |
Request timeout in seconds |
Connecting to AI Agents
The MCP server uses stdio transport — it communicates via stdin/stdout. Register it in your AI agent's MCP configuration.
Claude Desktop
Add to claude_desktop_config.json (typically at ~/Library/Application Support/Claude/claude_desktop_config.json on macOS):
{
"mcpServers": {
"moonraker": {
"command": "moonraker-mcp",
"args": [],
"env": {
"MOONRAKER_URL": "http://192.168.1.100:7125"
}
}
}
}
If you didn't pip install -e ., use the full Python path:
{
"mcpServers": {
"moonraker": {
"command": "/usr/bin/python3",
"args": ["-m", "moonraker_mcp.mcp_server"],
"env": {
"MOONRAKER_URL": "http://192.168.1.100:7125"
}
}
}
}
Cursor
Go to Settings → MCP → Add New MCP Server and fill in:
- Name:
moonraker - Type:
command - Command:
moonraker-mcp - Env (optional):
MOONRAKER_URL=http://192.168.1.100:7125
Or add to .cursor/mcp.json in your project:
{
"mcpServers": {
"moonraker": {
"command": "moonraker-mcp",
"args": [],
"env": {
"MOONRAKER_URL": "http://192.168.1.100:7125"
}
}
}
}
VS Code (Continue extension)
Add to ~/.continue/config.json:
{
"experimental": {
"mcpServers": [
{
"name": "moonraker",
"command": "moonraker-mcp",
"env": {
"MOONRAKER_URL": "http://192.168.1.100:7125"
}
}
]
}
}
Windsurf
Add to your Windsurf MCP config:
{
"mcpServers": {
"moonraker": {
"command": "moonraker-mcp",
"env": {
"MOONRAKER_URL": "http://192.168.1.100:7125"
}
}
}
}
Any MCP-compatible agent
The pattern is always the same: register a subprocess that runs moonraker-mcp (or python -m moonraker_mcp.mcp_server) with MOONRAKER_URL set to your printer's Moonraker address.
Example AI prompts
Once connected, an AI agent can use the tools. Some examples:
"What's the printer status?" → calls
moonraker_printer_info+moonraker_query_printer_objects
"Home all axes" → calls
moonraker_send_gcode({ "script": "G28" })
"Set spindle to 12000 RPM clockwise" → calls
moonraker_send_gcode({ "script": "M3 S12000" })
"Show the last 10 print jobs" → calls
moonraker_history_list({ "limit": 10 })
"What webcams are configured?" → calls
moonraker_webcams_list
"List all loaded Klipper objects" → calls
moonraker_printer_objects_list
Network notes
- The MCP server runs on the same machine as the AI agent (your dev machine). It connects to Moonraker over HTTP.
- If Moonraker is on a different machine (the printer), set
MOONRAKER_URLto the printer's IP (e.g.http://192.168.1.100:7125). - Make sure your dev machine's IP is in Moonraker's
trusted_clientslist (inmoonraker.conf).
Installing the CNC Agent on a Printer
Ansible playbook (recommended)
cd ~/E3CNC_UI
ansible-playbook ansible/playbooks/install.yml
This vendors the CNC agent into Moonraker, configures [cnc_agent] and [cnc_metadata] sections, deploys the WCS plugin and macros, builds the frontend, and restarts services.
Legacy bash script
cd ~/E3CNC_UI
./scripts/install_to_moonraker.sh
Updating via Moonraker Update Manager
The Ansible install and bash script both register an [update_manager E3CNC_UI] entry in moonraker.conf. After a git pull, the post_update_script automatically:
- Downloads the latest pre-built frontend (avoids running
vite buildon the printer) - Re-vendors the CNC agent files into
moonraker/components/ - Re-deploys the metadata extractor, WCS plugin, and macros
- Restarts Moonraker
Clicking Update in Mainsail's Machine → Update Manager panel is all you need.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file moonraker_mcp-0.1.1.tar.gz.
File metadata
- Download URL: moonraker_mcp-0.1.1.tar.gz
- Upload date:
- Size: 17.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
464bd575552a433a1ae93a3f3ac11e59a896615e4fe2a60a6714974fb0e10d39
|
|
| MD5 |
3ae57e8b09e55b600545a577cab97e3d
|
|
| BLAKE2b-256 |
316036707289202cddc8f43fa7ed05559bd12afd62f6c2f3068d866a0cd86c48
|
Provenance
The following attestation bundles were made for moonraker_mcp-0.1.1.tar.gz:
Publisher:
publish-moonraker-mcp.yml on E3CNC/E3CNC_UI
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
moonraker_mcp-0.1.1.tar.gz -
Subject digest:
464bd575552a433a1ae93a3f3ac11e59a896615e4fe2a60a6714974fb0e10d39 - Sigstore transparency entry: 1936593484
- Sigstore integration time:
-
Permalink:
E3CNC/E3CNC_UI@b38cfc903517db7a5abcd145846faebfa63bccd0 -
Branch / Tag:
refs/tags/moonraker-mcp-v0.1.1 - Owner: https://github.com/E3CNC
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-moonraker-mcp.yml@b38cfc903517db7a5abcd145846faebfa63bccd0 -
Trigger Event:
push
-
Statement type:
File details
Details for the file moonraker_mcp-0.1.1-py3-none-any.whl.
File metadata
- Download URL: moonraker_mcp-0.1.1-py3-none-any.whl
- Upload date:
- Size: 13.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7cc572206583d05324215bb23607790c3088e91b66f76b8c57539961aa46d09b
|
|
| MD5 |
930f2c5dfa3252eabcd4bb479b5d75b8
|
|
| BLAKE2b-256 |
1f471e812ae72d012e2959865a563cd91919c3db37513aa8c39bca6e714ef694
|
Provenance
The following attestation bundles were made for moonraker_mcp-0.1.1-py3-none-any.whl:
Publisher:
publish-moonraker-mcp.yml on E3CNC/E3CNC_UI
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
moonraker_mcp-0.1.1-py3-none-any.whl -
Subject digest:
7cc572206583d05324215bb23607790c3088e91b66f76b8c57539961aa46d09b - Sigstore transparency entry: 1936593555
- Sigstore integration time:
-
Permalink:
E3CNC/E3CNC_UI@b38cfc903517db7a5abcd145846faebfa63bccd0 -
Branch / Tag:
refs/tags/moonraker-mcp-v0.1.1 - Owner: https://github.com/E3CNC
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-moonraker-mcp.yml@b38cfc903517db7a5abcd145846faebfa63bccd0 -
Trigger Event:
push
-
Statement type: