CyberBrick

io.github.jarvislukPublished by GitHub account jarvislukv0.4.0Updated Nov 2, 2026

Drive the Bambu Lab CyberBrick desktop app: connect devices, edit firmware config, flash.

The publisher's own server: brick.blue

VerifiedSTDIODesktop onlyCloud & InfrastructureDeveloper Tools

Overview

AI-generated overview

Drives the Bambu Lab CyberBrick desktop app over CDP: connect devices, author firmware configs, flash boards and manage projects.

What you can do
  • Check app health, launch the app and read its console logs
  • Scan, pair and connect devices over Bluetooth or USB serial, and inspect device, board and BLE state
  • Read board config files and verify them by MD5 readback
  • Read, edit, reset or template the firmware config in the app's editor store
  • Flash configs, MicroPython or full firmware to a board, and send test commands
  • List, create, import, export, rename, delete, load and save projects, and manage app windows
When to use it
For people using the CyberBrick desktop app who want an assistant to walk the device setup flow: plan connections, author firmware parameters, flash and verify boards, and manage the project list without clicking through the UI.
Requirements
Local process on the same machine as the CyberBrick desktop app; Node.js 18+ (npm package cyberbrick-mcp, run via npx). The app must be reachable on its CDP endpoint, default 127.0.0.1:9223, configurable with CB_CDP_HOST and CB_CDP_PORT; cb_launch starts the app binary set by CB_APP_BINARY. Desktop only; no authentication declared.
Before you install
It is a pass-through to the app, so most tools act immediately: firmware config edits, project create/rename/delete/save, window close and flash_test change state, and project_delete cannot be undone. flash_mpy and flash_firmware reboot or can brick a board and need confirm=true only after explicit user approval; flash_config with hardwareMappings also upgrades firmware. cb_launch with kill_existing=true discards unsaved work. Device writes require a target matching exactly one device.

Installation

In SourceWeft

  1. Open CyberBrick in the dashboard and add it to a workspace.
  2. Enable the server for the chats that should use its tools.

Desktop only via STDIO. STDIO servers start a local process, so they need the SourceWeft desktop host.

Other MCP clients

Follow the launch instructions in the repository.

README

cyberbrick-mcp

English | 简体中文

An MCP server that drives the Bambu Lab CyberBrick desktop app (Electron) over the Chrome DevTools Protocol.

It covers the entire device setup workflow: hardware connection planning → firmware authoring → flashing.

Tools (41)

This server is a thin pass-through layer over the CyberBrick app: every tool calls the app's own API (store actions / device methods) and runs immediately. Exceptions: flash_mpy, flash_firmware, and flash_config with hardwareMappings (which upgrades firmware first) require confirm: true, set only after the user explicitly agrees. For device write operations, target must match exactly one device or the call is rejected.

Read-only / probing (readOnlyHint: true)

  • Infrastructure: cb_health, app_logs (app console logs, for following long flows such as upgrades or pairing)
  • Devices: device_list, device_detail, board_info, device_status, device_config_get, device_config_block, device_config_read (full readback + MD5), device_ble_state (live GATT / connectionCount state), device_pool_state, device_request
  • Connection planning: connect_scan_ports
  • Flash preflight: flash_check (which firmware / MPY / loader upgrades a hardwareMappings flash would trigger)
  • Firmware reading: firmware_config_get, firmware_edit_actions (semantic parameter docs for all 60 actions)
  • Project reading: project_state (page awareness + nextTools progressive disclosure), project_list, project_export

Write / flash (runs directly, MUTATING)

  • Launch: cb_launch (if the app is running without the debug port, it is only killed when kill_existing: true)
  • Connection: connect_bluetooth, connect_serial, device_ble_heal (repairs a NaN connectionCount so reconnects work without restarting)
  • Firmware authoring: firmware_config_set, firmware_config_edit, firmware_config_reset, firmware_config_load_template (loads a built-in template into the editor)
  • Flashing: flash_config (defaults to the SET_DEVICE_CONFIG file protocol; works with a single receiver and creates no new project), flash_mpy (destructiveHint: true), flash_firmware (destructiveHint: true), flash_test
  • Project management: project_create (6 built-in templates), project_import, project_rename, project_delete (destructiveHint: true), project_load, project_save, project_open_editor
  • Windows: window_list (read-only), window_close, window_close_others

Verification scripts

  • Unit tests (no app or hardware needed): npm test
  • Release version check: node scripts/check_release.mjs [vX.Y.Z]
  • Read-only path: node scripts/verify_readonly.mjs
  • Server and tool registration: node scripts/mcp_list.mjs
  • Local smoke test (needs the running app): node scripts/smoke.js
  • Project management smoke test (create → rename → export → import → load → save → delete): node scripts/smoke_project.mjs
  • Project management MCP E2E: node scripts/mcp_e2e_project.mjs
  • RC car end-to-end example (sender + receiver mappings → save → readback assertions → export; --flash adds flashing and an LED test): node scripts/demo_rc_car.mjs
  • Ad-hoc call to any tool: node scripts/mcp_call.mjs <tool> '<json>' [...]
  • Re-extract template data (after an app upgrade): python3 scripts/extract_templates.py

Running

Requires Node.js 18+ and the CyberBrick desktop app on the same machine.

MCP client config (JSON), installed from npm:

json
{  "command": "npx",  "args": ["-y", "cyberbrick-mcp"]}

From a local checkout:

bash
npm installnode src/server.js        # stdio MCP server

CDP port

Defaults to 127.0.0.1:9223 (kept off the common 9222). Override with CB_CDP_HOST / CB_CDP_PORT. cb_launch starts /Applications/CyberBrick.app/Contents/MacOS/CyberBrick by default; override with CB_APP_BINARY.

Safety rules

  • Never reads or exports auth tokens, private keys or AES keys (sanitize in connection.js filters by key name).
  • Destructive tools (flash_mpy, flash_firmware) carry destructiveHint and require confirm: true — the agent must first explain the impact to the user (writes the board / reboots / can brick) and get consent.
  • device_request only allows read-only methods (isInLoader, getDeviceById, and sendGetMessage for commands on the read-only allowlist).
  • cb_launch does not kill an already-running app by default (unsaved work would be lost); this needs an explicit kill_existing: true.
  • Deliberately not exposed: BIND_DEVICE, SET_PRIVATE_KEY, certificate flows, PIN flows (see ALLOWED_COMMANDS in src/core/devices.js).

Releasing

CI (.github/workflows/ci.yml) runs on every push to main and every PR: tests on Node 18/20/22/24, a server start-up check, the version check and npm pack --dry-run.

Pushing a vX.Y.Z tag runs .github/workflows/release.yml: verify → publish to npm (with provenance) → publish server.json to the MCP Registry → create the GitHub Release from the CHANGELOG section. Each step skips itself if that version is already out, so a failed run can simply be re-run.

  1. Bump the version in package.json / package-lock.json (npm version X.Y.Z --no-git-tag-version), server.json (both version fields) and src/server.js.
  2. Add a ## [X.Y.Z] - YYYY-MM-DD section to CHANGELOG.md.
  3. node scripts/check_release.mjs vX.Y.Z — must pass.
  4. Commit, then git tag vX.Y.Z && git push origin main vX.Y.Z.

A tag with a suffix (v1.0.0-rc.1) publishes to npm under the next dist-tag and is marked as a pre-release.

One-time setup:

  • npm: on npmjs.com, add a trusted publisher for this package (GitHub Actions, workflow release.yml, environment release). Trusted publishing can only be configured once the package exists, so for the very first release either publish once by hand or add an NPM_TOKEN repository secret (an npm automation token); remove the secret once trusted publishing is on.
  • MCP Registry: nothing to configure. The workflow signs in with GitHub OIDC, which is valid for the io.github.<owner>/ namespace of the repository it runs in.

License

MIT

Source: README.md at commit 5497d3a

Tools

41

cb_health

Check CyberBrick app health: CDP endpoint live, app version, renderer bridge access, device count. Call this first.

Takes no parameters.

cb_launch

Launch the CyberBrick desktop app with the CDP debug port (9223). Reuses a reachable CDP endpoint. If the app is already running without the debug port, it fails unless kill_existing=true (the app enforces a single-instance lock) — killing it discards unsaved work, so get the user's OK first. NOTE: must run from an unsandboxed shell.

Parameterstimeout_mskill_existing

app_logs

Read the CyberBrick app's renderer console, captured by this MCP server since it attached (ring buffer, 5000 lines; lines that mention tokens/keys/PINs/certs are never stored). Poll with since=<lastSeq> to follow long tasks such as flash_config with hardwareMappings (upgrade → send config → pairing). Per-message B0 traffic and keepalives are hidden unless includeNoise. Read-only.

ParametersgreplimitsincelevelsincludeNoise

device_list

List devices known to the CyberBrick app (zustand deviceListStore). Read-only.

Takes no parameters.

device_detail

Get detailed status for one device: connect state, loader mode, connection-pool entry. Read-only.

Parametersdevice_idrequired

device_pool_state

Inspect the internal Bluetooth connection pool (size + ids). Read-only.

Takes no parameters.

device_request

Call a read-only window.app.local method: isInLoader, getDeviceById, or sendGetMessage with a read-only B0 command (DEVICE_STATUS, GET_DEVICE_CONFIG, GET_BOARD_INFO, GET_BOARD_TYPE, GET_DEVICE_WIFI_MAC, SYSTEM_VERSION, MPY_PROJECT_INFO, MPY_CHECKSUM_INFO). Any other method or command is refused.

Parametersargsmethodrequired

board_info

Aggregated board info for one device: firmware/loader versions, hardware string, project string, SN, board type — read via B0 SYSTEM_VERSION + GET_BOARD_INFO + GET_BOARD_TYPE.

Parametersdevice_idrequired

device_status

ADC / channel status vector (DEVICE_STATUS, 10 bytes). Read-only.

Parametersdevice_idrequired

device_config_get

Board config file metadata (GET_DEVICE_CONFIG reqType=GET_FILE_INFO). file_size=0 means no config stored. Read-only.

Parametersdevice_idrequired

device_config_block

Fetch one board-config file block (GET_DEVICE_CONFIG reqType=GET_FILE_BLOCK). Use after device_config_get reports file_size>0. Read-only.

Parametersindexrequireddevice_idrequired

device_config_read

Read back the whole board config file (GET_FILE_INFO + every GET_FILE_BLOCK), trimmed to file_size, with its MD5 (compare with flash_config's md5) and the parsed config JSON. Read-only.

Parametersdevice_idrequired

device_ble_state

Live BLE link state per device: GATT connected, store vs. manager status, pool membership, loader mode and the BluetoothDevice connectionCount. connectionCountOk=false means every reconnect (enterLoader during upgrades, BLE drops) will fail with RECONNECTION_INTERRUPTED — fix with device_ble_heal. Read-only.

Takes no parameters.

device_ble_heal

Reset a non-finite (NaN/undefined) BluetoothDevice.connectionCount to 0 on live devices — the state markBluetoothDevice would have set — so the app's reconnect logic works again without power-cycling the board. No BLE I/O. Run before upgrades/pairing when device_ble_state shows connectionCountOk=false.

Takes no parameters.

connect_scan_ports

Scan connectable ports

Enumerate Web Serial ports and Web Bluetooth devices currently available to the CyberBrick app. Read-only — does not pair or connect. Use this to tell the user what hardware can be connected right now.

ParametersincludeKnownDevices

connect_bluetooth

Add device via Bluetooth

Drive the app's real add-device flow (BluetoothDeviceManager.requestDevice — the same one the MyDeviceDialog UI uses): starts a BLE scan filtered to CyberBrick devices (companyIdentifier 17882, manufacturer data prefix [99]), then auto-selects the matching device so the chooser resolves without UI. After it resolves, the app marks the device and the caller can verify with device_list. MUTATING (pairs a device).

ParametersdeviceIdtimeoutMsdeviceName

connect_serial

Select USB/Serial port

Ask the app's main process to auto-select a Web Serial (USB-C) port (window.electron.ipcRenderer.autoSelectSerialPort, strategy "first") and return its metadata plus the BLE-connected board it belongs to (USB serial number = chip MAC, matched against each board's GET_DEVICE_WIFI_MAC). In this app the serial link only serves the USB flash (rescue flasher) feature — config, pairing, upgrades and every other device tool go over Bluetooth, so this does not make a board usable by the other tools. Opens nothing on the board.

Takes no parameters.

firmware_config_get

Get current firmware config

Read the current firmwareConfig from the app store (window.app.useFirmwareConfigStore). This is what would be burned to the board. Read-only.

Takes no parameters.

firmware_edit_actions

List firmware editing actions

Semantic documentation for the firmware-config store actions (window.app.useFirmwareConfigStore) — the surface behind firmware_config_edit. Returns enums (receiverKey, actuator, device, configType), grouped action names, and per-action arg signatures. Pass action=<name> to get the doc for one action. Read-only, no app connection required.

Parametersaction

firmware_config_set

Set full firmware config

Replace the whole firmware config via the app store's setFirmwareConfig. Immediately applies to the app store (and the next burn). MUTATING — writes to the app's firmware config.

Parametersconfigrequired

firmware_config_edit

Edit one config field

Call a single firmware store action on the app store (e.g. updateReceiverChannel, updateSenderChannel, changeSwitchState). Immediately applies to the editor config. MUTATING. Use firmware_edit_actions first to get the exact arg signature (positional args, enums like receiverKey/actuator) for the action you want.

Parametersargsactionrequired

firmware_config_reset

Reset config to empty defaults

Clear the firmware config to empty defaults via the app store's resetFirmwareConfig. Immediately applies. MUTATING.

Takes no parameters.

firmware_config_load_template

Load built-in template into editor

Replace the editor config with one of the app's built-in project templates (same data as project_create, in the app's UI language). By default keeps the loaded project's id/name so project_save overwrites it; keepIdentity=false loads it as an unsaved new config. Marks the editor modified; nothing is written to the project list or board until project_save / flash_config. MUTATING.

ParameterstemplaterequiredkeepIdentity

flash_config

Burn firmware config to board

Write a firmwareConfig to the board. Default: the app's SET_DEVICE_CONFIG file protocol (FILE_INFO(md5,size) → chunked FILE_BLOCK via sendGetMessage) — works for a lone receiver, burns firmwareConfig if given else the current editor config, to exactly one target device (ambiguous or unmatched targets are refused). The device must be connected (else DEVICE_NOT_CONNECTED → call connect_bluetooth). Returns {ok, verified, bytes, chunkSize, blocks, md5, readback} — verified=true when the board reports the written size — or {stage, ...} on failure. Passing hardwareMappings switches to the app's runSendConfigTask (burns a saved project, needs a sender board; never creates a project). That path can also upgrade firmware / MPY / loader first — preview with flash_check and pass confirm=true only after the user approved those upgrades. Executes immediately — OVERWRITES the board's stored config. MUTATING / writes to hardware.

ParameterstargetconfirmfirmwareConfigfirmwareListIdhardwareMappings

flash_check

Preview upgrades for a hardwareMappings burn

Dry-run of flash_config's hardwareMappings path: calls the app's checkDeviceConfigSync and reports, per board, which firmware / MPY / loader upgrades runSendConfigTask would run before sending the config and pairing. Nothing is written. Use it to get the user's consent for upgrades first. upgradeTargets is exactly what the run executes (the app's log may still mention a loader upgrade it then skips). Read-only.

ParametersfirmwareListIdhardwareMappingsrequired

flash_mpy

MicroPython firmware update

Run a MicroPython firmware update via the app's updateLoaderFirmwareMpy (START_MPY_UPDATE). Writes mpy.img and REBOOTS the board. DESTRUCTIVE — requires confirm=true after explicit user approval. Default path upgrades to the built-in RC MPY (mpyType=1); passing userMpyConfig targets a design MPY. Experimental: the built-in path still needs live validation (see docs/MPY固件链路笔记.md).

ParametersregiontargetconfirmrequiredmpyTypedesignIdchecksum0userMpyConfigeraseFirmwareConfig

flash_firmware

Full system firmware upgrade

Run a full system firmware flash (SYSTEM_UPGRADE) via the app's updateLoaderFirmwareMpy with shouldUpgradeFirmware=true. Executes immediately — multiple reboots, CAN BRICK the device if interrupted. Requires firmwareBinaryB64: the MCP does not replicate the app's cloud package fetch (auth headers + certificate decryption are out of scope), so you must supply the .bin yourself (base64). Requires confirm=true after explicit user approval. DESTRUCTIVE.

ParametersregiontargetconfirmrequiredtargetVersionfirmwareBinaryB64required

flash_test

Send test/control command

Send a control/test command to a connected device via the app's sendTestCommand. Executes immediately — drives an actuator/output on the board. MUTATING.

Parameterstargetcommandrequired

project_state

Get project page state

Read the app's current context: active route (hash), project list summary, and editor state (isModified, configType). Returns a nextTools list of the tools relevant right now — call this first when working with CyberBrick projects, then act. Read-only.

Takes no parameters.

project_list

List projects

List CyberBrick projects via the app store's getShowList(): configId, type, configName, designLink, lastModifiedTime. Pass include=full to fetch one project's complete config body via getFirmwareById. Read-only.

Parametersid

project_create

Create project from template

Create a new CyberBrick project from a built-in template (the app's createProjectFromTemplate flow: template config + addFirmware). Templates: forklift, truck, forklift_and_truck, ball_car, official_remote, none, custom. MUTATING (adds a project to the app's list).

Parametersnametemplaterequired

project_import

Import project from JSON content

Import a project from its JSON content (the app's importProjectFromFileContent flow): validates config_version (rejects files newer than the app supports), forces design_id/region to app defaults, adds to the project list. Pass the file content as a string — read the file yourself first. MUTATING (adds a project).

Parametersnamecontentrequired

project_export

Export project as JSON content

Export a project's config as JSON content — the same serialization the app's export uses (runtime fields stripped, version stamped). No save dialog; write the returned content to a file yourself. Read-only.

Parametersidrequired

project_rename

Rename project

Rename a project via the app store's renameFirmware. MUTATING. Max 31 chars (app validation).

Parametersidrequirednamerequired

project_delete

Delete project

DESTRUCTIVE: permanently deletes the project via the app store's deleteFirmware. This cannot be undone — the project config is removed from the app's persisted list. No confirmation is added by MCP.

Parametersidrequired

project_load

Load project into editor

Load a project's config into the app's firmware editor store (setFirmwareConfig(getFirmwareById(id)) + setConfigType), the same thing the app does when you open a project. After loading, use firmware_config_edit to change parameters, then project_save to persist. MUTATING (replaces the current editor config).

Parametersidrequired

project_save

Save editor config as project

Persist the current editor config into the project list (the app store's updateFirmware: updates by id, adds if new) and mark the editor as saved. MUTATING (writes the project list).

Takes no parameters.

project_open_editor

Open project editor window

Open the project editor (the app's openProjectEditor): loads the config into the editor store, then opens /project/edit?firmwareId=<id> either in a new app window (default, via the app's createWindowWithPath) or by navigating the current window. MUTATING (loads config, opens window).

Parametersidrequiredtarget

window_list

List app windows

List the CyberBrick app's open windows: `openWindows` is the live truth (CDP page list with titles + hash routes), `storeWindows` is the window-state store's persisted id map (may be stale) — its ids are what window_close accepts. Also reports which window this MCP session is connected to (currentWindowId) and whether its editor has unsaved changes. Read-only.

Takes no parameters.

window_close

Close an app sub-window

Close a CyberBrick app window by its windowId (from window_list). Uses the app's own closeSubWindow (window:close-sub-window IPC) — the same path as the window's close button; unsaved changes trigger the app's own confirm dialog, which the MCP does not bypass. The MCP-connected window cannot be closed (REFUSE_CLOSE_CURRENT). Each project_open_editor with target="new" opens one of these — close them to avoid window buildup. MUTATING.

ParameterswindowIdrequired

window_close_others

Close all sub-windows except current

Close every CyberBrick app window except the one this MCP session is connected to. Use to clean up editor windows accumulated from project_open_editor. Unsaved changes surface the app's own confirm dialogs. MUTATING.

Takes no parameters.

Version history

1
  1. v0.4.0LatestOct 26, 2026

Score

90% of the applicable checks met

How complete this listing is, computed from the registry entry, the endpoint and public sources. Not a rating of the server and not a statement that it is safe or working today: reachability is a dated check, and no installs or reviews go into the score.

  • Reached in the last 30 days25 pts
  • Auth declared10 pts

    Declare the credential headers in the registry entry, or keep the endpoint answering the probe so its auth can be classified.

  • Tools listedRequired15 pts
  • DescriptionRequired15 pts
  • Logo10 pts
  • Documentation15 pts
  • License10 pts

Other Brick integrations