mcp-bambu
Provides LAN-based monitoring and control for Bambu Lab 3D printers, including status, file management, print control, filament tracking, maintenance alerts, and failure diagnosis via MQTT telemetry.
Publishes a static dashboard generated from monitor data to Cloudflare Pages.
Sends push notifications for printer alerts, failures, and operational events to an ntfy server.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@mcp-bambuwhat's the status of all my printers?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
mcp-bambu
Local-network tooling for a small fleet of Bambu Lab 3D printers: an MCP server so Claude Code can see and drive the machines, an always-on monitor that turns the MQTT telemetry stream into alerts and a durable event log, and a media sync. No cloud dependency — everything talks to the printers directly over the LAN.
It exists because the printers are poor witnesses to their own failures. A P1S
will report FINISH on a print that produced a six-hour bird's nest, its own
logs are encrypted, and the only usable record of what actually happened is the
live MQTT stream — which nothing keeps unless you keep it.
entry point | run as | what it does |
| MCP (Claude Code) | status, files, print control, filament, maintenance, diagnosis |
| launchd, always on | MQTT watcher; alerts, event log, filament billing, maintenance clock |
| launchd, hourly | pulls timelapses to the NAS |
| by hand | render + lint + record a model (see below) |
Three entry points, one config, one set of credentials.
Requirements
Python 3.11+
A Bambu Lab printer reachable on the LAN, and its access code (printer screen → Settings → Network/WLAN)
Optional: an ntfy server for push notifications
Optional, for
bambu_mcp.export: OpenSCAD andprint-lint
Related MCP server: CNCjs MCP Server
Install
git clone <this repo> && cd mcp-bambu
python3 -m venv .venv && . .venv/bin/activate
pip install -e .The editable install is not optional — see the first gotcha below.
Configure
cp config.example.toml config.toml # printers, paths, ntfy
cp creds.example.toml creds.toml # access codes
chmod 600 creds.tomlBoth real files are gitignored. config.toml holds printers, paths and ntfy;
creds.toml holds access codes and the ntfy password. Adding a printer is one
[[printers]] block plus its access code, and it joins all three entry points
automatically.
serial must be exact — it is the MQTT topic (device/<serial>/report).
Both it and the IP are on the same screen as the access code.
Alert routing lives in alert_rules.toml, re-read on every event so edits need
no restart. A missing or corrupt rules file fails open — everything alerts —
because on this fleet quiet has meant broken. Maintenance rules deliberately
fail quiet: a missed reminder is an inconvenience, a missed fault is not.
Run
python -m bambu_mcp.monitor # foreground; run under launchd in anger
python -m bambu_mcp.server # registered as an MCP server in Claude CodeChecks
pip install -e ".[dev]"
pytest tests/ # 105 tests, no hardware needed
pylint bambu_mcp tests # 10.00/10
bandit -c pyproject.toml -r . # 0 issuesBoth linters are configured in pyproject.toml, and every disabled check
carries the reason it is disabled. Nothing is silenced to raise a score: the
subprocess warnings are accepted because the calls pass argument lists and
never touch a shell, and the two # nosec B310 markers point at the scheme
guard in Notifier._request() that bandit cannot see from the call site.
The dashboard
A static page, published to Cloudflare Pages. There is no server and no API:
publish.py reads what the monitor already wrote and exports
site/data/*.json; site/index.html fetches them.
python -m bambu_mcp.publish # export only
./run_and_publish.sh # export, then wrangler pages deployFreshness is the whole problem with a static page. It is a snapshot, and a stale one is indistinguishable from a calm fleet - which is this repo's oldest lesson. So there are two guards, deliberately overlapping:
run_and_publish.shturns a failed export or a failed deploy into an ntfy alert. Neither step can report its own death, and Cloudflare will happily keep serving the last good build forever.Every payload is stamped, and the page computes its own age in the browser. A JSON file cannot know how long it has been sitting there; only the viewer's clock can tell a fresh deploy from a fossil. So the page says so even if the publisher never runs again.
Cadence is a parameter: fast while anything is printing, slow when the fleet is
idle. any_active in the payload exists for a wrapper to decide that. See
com.billfordx.bambu-publish.plist.example - an example, not an installed job.
What is published. No IPs, serials, access codes, hostnames or filesystem
paths - the payload is built to carry none of them, and a test asserts it.
Job names DO appear, because they are what a dashboard is for; set
redact_jobs = true under [publish] to leave them out. Generated payloads are
gitignored, so they reach Cloudflare and never the repo.
Findings that cost real time — do not re-derive them
The printers' own
.logfiles are encrypted. Only Bambu support can read them. Shipping them anywhere is pointless; the live MQTT report stream is the only usable local fault source.MQTT (8883), FTPS (990) and the camera (6000) all work in CLOUD mode on the P1S. LAN Only is not required for monitoring — but the H2D will not display an access code outside LAN Only, which is the real reason to convert it. Note the cost: LAN Only ends Bambu Handy, which is cloud-only.
Reads work; starting a print may not. A
project_filecommand was refused by a cloud-mode P1S withHMS_0500_0500_0001_0007— "MQTT Command verification failed" — whilesystem/ledctrlsucceeded over the same connection seconds later. Monitoring is unaffected.Undocumented HMS codes are in a table on your own disk. The public wiki 404s on some of them. Bambu Studio caches the real per-model table at
~/Library/Application Support/BambuStudio/hms/hms_en_<model>.json(01P= P1S). Search it for the code with the underscores stripped.One MQTT client per printer. Several short-lived connections opened a few seconds apart made both machines return empty reports — no error, no refusal, no log line. A second collector does not fail loudly, it silently returns nothing. Read this project's event log instead of opening a second connection.
The export wrapper
python -m bambu_mcp.export ufo.scad -o ufo_body.stl -D part=body --layer-height 0.2Renders, lints and records job → source + parameters in one step. Use it
instead of calling openscad directly — the manifest entry is what makes a
later failure diagnosable, since the printer only ever knows a filename.
Diagnosis
On FAILED or PAUSE the monitor classifies the failure and pushes a second
notification saying why. The machine's own fault reporting outranks anything
inferred: if the printer raised an HMS code, that is the answer and the
geometry is not touched. Only when no fault was reported does it re-lint the
source and locate the problem at the height the print stopped.
bambu_repair will then sweep the recorded parameters, render each candidate
with OpenSCAD and score it with print-lint, so a proposal is only ever
returned because it measurably beat the original. If nothing improves, that
is the answer — "this needs a shape change, not a number."
Both run on a background thread. A dozen OpenSCAD renders on paho's callback thread would stall telemetry for minutes and trip the staleness alert.
Gotchas
mcpis pinned<2. 2.x removed the low-levelServerdecorator API this is written against.The package must be
pip install -e .'d into its venv. It is registered aspython -m bambu_mcp.server, and-mresolves from the current working directory — so it starts fine from the project dir and fails everywhere else, which is where Claude Code actually launches it. Worse,claude mcp listinherits the shell's cwd, so running it from the project directory reports a cheerful "Connected" for a server the session cannot start.The P1S never decrements filament remaining.
remainis -1 on every slot, tagged or not. Hencefilament.py, which bills each finished job from the slicer's own figures. The H2D does report it, so the same field carries two different confidence levels depending on the machine.AMS trays are keyed by unit and tray, never tray alone. Both AMS units number their trays 0-3, so flattening on tray id gave the H2D's eight trays four ledger keys — the units overwrote each other on every sync, zeroing
used_gand reporting spool swaps that never happened. Keys areA1..A4/B1..B4, lettered because Bambu's own fault strings say "AMS A". Old numeric ledgers migrate on read.chamber_temperis not a sensor on the P1S. It stayed pinned at exactly 5 through a 180 °C swing while nozzle and bed tracked normally. The H2D omits the key entirely. One machine lies, the other is silent — do not default it to zero and plot it.subtask_nameis empty at FINISH, and is often the slicer profile rather than the model (0.16mm layer, 2 walls, 10% infill). The job name only appears during SLICING/PREPARE, so the monitor caches the last one it saw — without that, no finished print could ever be charged.SD card filenames contain spaces and commas. Parse FTP listings with
split(maxsplit=8)and percent-encode URLs, or files silently vanish.Timelapse is a slicer setting and does not persist across projects. With it off there is no independent check on a completion at all, which matters given the P1S will report
FINISHon a failure. The monitor firesfinish_unverifiedwhen a print ends with no recent timelapse.
Tested on
A Bambu Lab P1S and an H2D, on macOS, with launchd running the monitor and the sync. Nothing here is macOS-specific except the launchd plists and the Bambu Studio cache paths; the rest is plain Python over MQTT and FTPS.
This is personal tooling for one small fleet, published because the findings above were expensive to arrive at and are hard to find written down anywhere else. It is not a product and carries no support promise.
License
MIT - see LICENSE.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- AlicenseAqualityBmaintenanceEnables comprehensive control and monitoring of Bambu Lab 3D printers through Claude using local MQTT, FTPS, and X.509 authentication. Users can manage print jobs, monitor real-time status, handle filament through AMS, and adjust hardware settings like temperature and lighting.243017MIT
- AlicenseAqualityDmaintenanceBridges Claude Code to CNCjs to enable remote control and monitoring of GRBL-based CNC machines. It provides a comprehensive toolset for managing G-code jobs, machine movement, and safety operations through natural language.301MIT
- AlicenseNot gradedqualityDmaintenanceEnables users to connect Claude with various 3D printer management systems, allowing tasks like printer status monitoring, file management, print job control, and STL file manipulation.103GPL 2.0
- AlicenseNot gradedqualityDmaintenanceEnables AI assistants to interact with Bambuddy's 3D printer management API, including printer status, print queue, filament spools, and camera snapshots.5GPL 3.0
Related MCP Connectors
WHOOP recovery, strain, sleep and workouts in Claude via official WHOOP OAuth. Free, open source.
Connect Claude to Fathom meeting recordings, transcripts, and summaries
Real-time chat hub for AI agents — Claude Code, Cursor, Cline, Codex over MCP or REST.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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/billford/mcp-bambu'
If you have feedback or need assistance with the MCP directory API, please join our Discord server