formlabs-local-mcp
This MCP server lets an AI client drive Formlabs PreForm end-to-end: build a print scene, prep and validate models, export files, and send jobs to printers.
Setup & diagnostics:
health_check,preform_status, andinstall_preform_server(downloads, signature-verifies, and installs PreFormServer).Scene management: create, list, get, update, delete scenes, and load existing
.formfiles.Model handling: import STL/OBJ/3MF/STEP, get/update/duplicate/replace/delete models (move, rotate, scale, rename, lock).
Print prep:
auto_orient,auto_support,auto_layout(SLA),auto_pack/fill_build_chamber/pack_and_cage(SLS),fill_build_platform,hollow_model,label_model.Drain holes:
auto_add_drain_holesand manualadd_drain_holes.Analysis: full print validation, cup detection, unsupported minima, supportedness, thin walls, interferences, and print-time estimation.
Export: save as
.form, screenshots (.png/.webp), and.fpsprint-settings files.Printers: list/get/discover devices and
print_to_printer(including virtual printers for dry runs).Materials & account: list printer types/materials, plus
login,logout,get_userfor remote/Fleet Control printing.
Click on "Deploy 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., "@formlabs-local-mcp Import model.stl, auto-orient, and estimate print time."
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.
formlabs-local-mcp
An MCP server for the Formlabs Local API. It lets Claude Code, Claude Desktop, Cursor and any other MCP client drive PreForm from a chat prompt:
"Import
~/parts/bracket.stl, orient and support it for the Form 4 in Black V5, estimate the print time, then save it as~/jobs/bracket.form."
See it work: https://mkebiclioglu.github.io/formlabs-claude-skills/ (a downloaded bracket to a validated Form 4 job in one prompt; spin the result, compare materials)
Docs and the Claude Code plugin: https://mkebiclioglu.github.io/formlabs-claude-skills/docs.html

Install
Needs Node.js 20 or newer. Nothing else. Published on npm as
formlabs-local-mcp with build
provenance. Pin the version you tested with:
claude mcp add --scope user formlabs -- npx -y formlabs-local-mcp@1.0.14Using Claude Code? The plugin installs this server plus print-prep skills in one line, so you do not need the command above.
For other MCP clients, put the same command in their config:
{
"mcpServers": {
"formlabs": {
"command": "npx",
"args": ["-y", "formlabs-local-mcp@1.0.14"]
}
}
}Then ask Claude to run health_check. If PreFormServer (Formlabs' headless PreForm)
is not installed yet, the server says so and offers the install_preform_server
tool, which downloads the current release from Formlabs, verifies Formlabs' code
signature, and installs it into a folder you own. From a shell the same thing is:
npx -y formlabs-local-mcp@1.0.14 install-preformIf you already have PreFormServer.app in /Applications, it is picked up as is.
Related MCP server: MCP Server Demo
Commands
Command | What it does |
| Serve MCP over stdio (what MCP clients run). |
| Download, verify and install the latest PreFormServer. No-op when up to date; |
| Show what is installed, which mode is active, and whether Formlabs has a newer release. |
Tools
Area | Tools |
Setup |
|
Scenes |
|
Models |
|
Prep |
|
Drain holes |
|
Analysis |
|
Export |
|
Printers |
|
Materials |
|
Account |
|
Tools carry MCP annotations (readOnlyHint, destructiveHint) so clients can ask
before print_to_printer, save_form, install_preform_server or any delete.
Fuse X1: PreFormServer 3.63 (3.63.0 and 3.63.1) prepares jobs for it (machine_type FUSX-1-0,
material_code FLP12G01, 0.11 mm, the one setting it ships) but leaves the
family out of list-materials; list_printer_types and list_materials add it
with an unlisted note until Formlabs lists it. No other material or layer
height, and no auto_pack, in this release.
No printer yet? PreFormServer ships a built-in virtual printer for every model
(list_devices shows them with connection_type: VIRTUAL), and
print_to_printer with "Form 4" runs the whole job upload against one, so a
pipeline can be rehearsed end to end before hardware arrives. The integration
tests do exactly that on macOS, Windows and Linux.
Tracks Formlabs Local API 0.9.31 (PreFormServer 3.63.1). The installer picks the Apple Silicon
build on arm64 Macs and the Intel build elsewhere, falling back to Intel for releases that only ship it.
Configuration
None needed in the common case. Everything is an environment variable on the MCP
server entry (or in the env block of ~/.claude/settings.json for Claude Code).
Variable | Default | Purpose |
| auto-detected | PreFormServer executable if it lives somewhere unusual. |
|
| Port PreFormServer listens on (local port of the tunnel in remote mode). |
|
| Connect to a PreFormServer you run yourself (disables spawning). |
|
|
|
|
| Seconds to wait for PreFormServer to come up. |
|
| Longest one operation (supports, packing, upload) may take. |
|
| PreFormServer telemetry is off when spawned; |
|
| Command prefix used to start PreFormServer, e.g. |
|
|
|
| unset |
|
| home directory | Directories the model may read from and write to. |
|
| Allow paths through dot-directories such as |
| unset | Formlabs account for |
|
| Permit |
| unset | Run PreFormServer on another machine over ssh (see below). |
|
| ssh port for the remote host. |
| well-known paths | PreFormServer executable on the remote host. |
|
|
|
|
| Linux only: accept a download whose Authenticode signature cannot be checked (install |
Linux
Formlabs ships PreFormServer for macOS and Windows only. Three ways to use it from Linux, in the order most people should try them:
A container running PreFormServer under Wine (recommended for servers and automation). preform-linux packages the Windows build with Wine and Xvfb, headless, no GPU, signature-checked at first start, with printers reached by IP or through a Formlabs account. Point this server at it:
PREFORM_SERVER_URL=http://127.0.0.1:44388
PREFORM_SERVER_PATH_STYLE=wine
PREFORM_PATH_MAP=/home/me/preform-linux/jobs=Z:/jobsFiles under the mapped directory are sent as Z:/jobs/..., which is how PreFormServer
inside the container sees them; everything else works exactly as on macOS.
Wine on this machine. install-preform fetches the Windows build and verifies its
Authenticode signature with osslsigncode; the server then starts it through wine
with headless defaults (QT_OPENGL=software, no Mono/Gecko prompts) and writes file
paths as Z:/home/me/... automatically. Needs Wine 11.5 or newer from
WineHQ (distro Wine 9.0 cannot load PreFormServer
3.63) and a display: PREFORM_LAUNCHER="xvfb-run -a wine" on a headless box. Wine
11.13+ runs it as is; 11.5 to 11.12 need preform-linux's small dnsapi.dll shim. LAN
printer discovery by mDNS does not work under Wine; pass a printer's IP to
discover_devices and print_to_printer instead, or login for Fleet Control. A weekly
CI job
runs the smoke test this way.
Remote mode. Run PreFormServer on any Mac or Windows box on your network and let the MCP server on Linux drive it over ssh:
PREFORM_REMOTE_HOST=me@studio-mac.localOne ssh session (keys only, BatchMode) forwards a loopback port and starts
PreFormServer on the remote machine, so it stops when the MCP server does. Input
files are copied over with scp into a per-session staging folder under the remote
user's home; .form files and screenshots are copied back. The remote host needs
PreFormServer installed (run install-preform there) and a POSIX shell over ssh
(macOS, Linux). For a Windows remote host set PREFORM_REMOTE_SPAWN=0 and start
PreFormServer yourself.
Security
PreFormServer is a plain-HTTP server with no authentication that reads and writes files as you. This server keeps that surface small:
Path guard rails. Every file path a tool receives must be absolute, resolve (symlinks included) to somewhere under
FORMLABS_ALLOWED_PATHS(default: your home directory), avoid hidden directories, and carry the right extension (models in,.form/.png/.webp/.fpsout).Verified installs.
install_preform_serveronly downloads over HTTPS fromdownloads.formlabs.comwith Formlabs' release path layout, scans the archive for path traversal before extracting, and checks the code signature before moving anything into place: Developer ID teamKVPE3R79SRplus notarization on macOS, a valid Authenticode signature from Formlabs on Windows,osslsigncodeon Linux. A failed check leaves the previous install untouched.Credentials stay out of the chat.
logintakes no arguments; it readsFORMLABS_USERNAME/FORMLABS_PASSWORDfrom the environment and never returns tokens to the model. It refuses non-loopback servers unless you opt in.Short-lived server. PreFormServer runs only while an MCP client is connected and is stopped on exit. Telemetry is disabled.
Remote mode uses ssh keys only, validates the host string so it can never be parsed as an ssh option, binds the forward to 127.0.0.1, and sanitizes staged file names.
Supply chain. Two runtime dependencies (
@modelcontextprotocol/server,zod), a lockfile, SHA-pinned GitHub Actions, Dependabot, CodeQL. Releases are published from CI with npm provenance and 2FA-only access, sonpm audit signaturescan check that what you installed came from a tagged commit here.
One thing this server cannot change: PreFormServer binds to all network
interfaces (*:44388) and has no option to bind loopback only. On a shared or
untrusted network keep your OS firewall on so other machines cannot reach that port.
Contributing
git clone https://github.com/mkebiclioglu/formlabs-local-mcp.git
cd formlabs-local-mcp
npm install
npm test # unit tests, no PreFormServer needed
npm run typecheck && npm run lint
npm run build
npm run smoke # end-to-end against a real PreFormServerIssues and PRs are welcome; see CONTRIBUTING.md for how to add a tool and what CI checks. Questions and "here is what I printed" go in Discussions. Security reports: SECURITY.md.
License
MIT. The Formlabs API itself is covered by the Formlabs API License Agreement; this project only makes HTTP calls to PreFormServer and ships no Formlabs code. Not affiliated with or endorsed by Formlabs Inc.
Available Tools
45 toolsadd_drain_holesA
Add hand-placed drain holes to one model. Each entry needs position {x,y,z}, orientation, diameter_mm, depth_mm (number or "AUTO") and create_plug; max_search_distance (mm) lets PreForm snap the hole onto the nearest surface. Prefer auto_add_drain_holes unless the user gives coordinates.
Inputs: model_id (required), drain_holes (required), scene_id.
auto_add_drain_holesA
Place drain holes automatically on every model that cup detection flags. Runs detect_cups, then for each cupped model samples points under its bounding box and lets PreForm project them onto the surface (depth AUTO). Models without cups are skipped. A "no surface found" warning means the cups are on a side face: offer add_drain_holes instead.
Inputs: models, scene_id, diameter_mm, max_holes_per_model.
auto_layoutA
Arrange models on the build platform. SLA printers only (machine types starting with FORM- or FRM). For SLS printers (Fuse) use auto_pack. mode="DENTAL" uses the Dental Workspace layout.
Inputs: mode, models, scene_id, lock_rotation, +3 more.
auto_orientA
Rotate models to the orientation PreForm judges best for printing. mode="DENTAL" uses the Dental Workspace algorithm; tilt (degrees) applies only in DENTAL mode.
Inputs: mode, tilt, models, scene_id.
auto_packA
Pack all models into the 3D build chamber. SLS printers only (machine types starting with FS or PILK; PreFormServer 3.63 refuses it for the Fuse X1, FUSX-1-0, where models stay where import_model put them). For SLA printers use auto_layout. packing_mode is PACK_HEIGHT (minimize build height, faster print) or PACK_VOLUME (tightest packing).
Inputs: seed, scene_id, packing_mode, model_spacing_mm, +1 more.
auto_supportB
Generate support structures. Leave parameters unset for PreForm's defaults. density and slope_multiplier are unitless factors around 1.0; raft_type is FULL_RAFT, MINI_RAFT or MINI_RAFTS_ON_BP.
Inputs: models, density, scene_id, raft_type, +8 more.
create_sceneA
Create a new scene for a printer and material. Returns the scene including its id. Provide EITHER machine_type + material_code + layer_thickness_mm OR the absolute path of a .fps print-settings file. Get valid codes from list_printer_types and list_materials; never guess them.
Inputs: fps_file, machine_type, material_code, print_setting, +1 more.
delete_modelBDestructive
Remove a model from the scene.
Inputs: model_id (required), scene_id.
delete_sceneADestructive
Delete a scene and its models. Deleting "default" resets it to empty.
Inputs: scene_id (required).
detect_cupsARead-only
Count resin cups (trapped-resin pockets) per model. Faster than full validation.
Inputs: scene_id.
detect_minimaARead-only
Count unsupported local minima per model (points that would print in mid-air).
Inputs: scene_id.
detect_supportednessARead-only
Percentage of each model's surface that is unsupported (PreForm's red shading).
Inputs: scene_id.
detect_thin_wallsARead-only
Find wall regions thinner than threshold_mm per model, with volumes and bounding boxes.
Inputs: threshold_mm (required), models, scene_id.
discover_devicesBRead-only
Scan the local network for Formlabs printers. Pass ip_address to probe one host.
Inputs: ip_address, timeout_seconds.
duplicate_modelA
Make count copies of a model. Returns the scene. Run auto_layout or auto_pack afterwards.
Inputs: model_id (required), count, scene_id.
estimate_print_timeARead-only
Estimate print time in seconds for the scene. Read material usage from get_scene.
Inputs: scene_id.
fill_build_chamberA
Duplicate the given models until the SLS build chamber is full and pack them. SLS only; returns new_model_ids. Set fill_to_height_mm to fill only part of the chamber.
Inputs: models, scene_id, model_spacing_mm, fill_to_height_mm, +1 more.
fill_build_platformA
Duplicate the given models as many times as fit and lay the copies out. SLA only; returns new_model_ids. For SLS printers use fill_build_chamber.
Inputs: models, scene_id, model_spacing_mm, placement_margin_mm.
get_deviceARead-only
Status of one printer: connection, tank and cartridge material, time remaining.
Inputs: device_id (required).
get_interferencesARead-only
List pairs of model ids that overlap or sit closer than collision_offset_mm.
Inputs: scene_id, collision_offset_mm.
get_modelARead-only
Get one model's properties: transform, bounding box, supports, lock state.
Inputs: model_id (required), scene_id.
get_print_validationARead-only
Full printability check per model: cups, unsupported_minima, undersupported, has_seamline.
Inputs: scene_id.
get_sceneARead-only
Get a scene: its models (ids, bounding boxes, supports), print settings, material usage and build volume.
Inputs: scene_id.
get_userARead-only
Return the Formlabs account currently logged in (after login).
Inputs: no named parameters.
health_checkARead-only
Return the PreFormServer version. Call this first to confirm the server is reachable; it starts PreFormServer if needed.
Inputs: no named parameters.
hollow_modelA
Hollow models to save resin. Follow up with auto_add_drain_holes so resin can escape.
Inputs: models, scene_id, feature_size_mm, wall_thickness_mm.
import_modelA
Import a model file (STL, OBJ, 3MF, STEP) into a scene. file must be an absolute path. Returns the model with its id. Defaults differ from the raw API: repair_behavior=REPAIR (the API default ERROR fails on slightly broken meshes most CAD tools export) and units=MILLIMETERS (use INCHES for inch files, DETECTED to let PreForm guess). After importing, the scene is re-read and the call fails with IMPORT_PRODUCED_EMPTY_SCENE if no model was added: the file is malformed, do not retry.
Inputs: file (required), name, scale, units, +5 more.
install_preform_serverADestructive
Download the latest PreFormServer from Formlabs (about 170 MB), verify Formlabs' code signature, and install it into a user-owned folder. Ask the user before calling this. Safe to call again: it is a no-op when the installed version is already the latest.
Inputs: force.
label_modelA
Emboss or engrave text onto a model's surface. position is the label centre {x,y,z} in scene mm; orientation (Euler degrees) sets the text direction with +x along the text and +z as the surface normal.
Inputs: label (required), depth_mm (required), model_id (required), position (required), +4 more.
list_devicesARead-only
List printers PreFormServer knows: discovered LAN printers (run discover_devices to refresh), Fleet Control queues and Dashboard printers after login, and its built-in virtual printers (connection_type VIRTUAL, one per model such as "Form 4"), which accept print_to_printer as a hardware-free dry run of the whole upload path.
Inputs: can_print.
list_materialsARead-only
List printers with their materials and print settings. Each material setting's scene_settings holds the exact machine_type, material_code, print_setting and layer_thickness_mm for create_scene. Pass machine_type to keep only one printer family; the full list is large.
Inputs: machine_type.
list_printer_typesARead-only
Short list of printer families with machine_type codes and build volumes. Use it to map a printer name ("Form 4", "Fuse 1+", "Fuse X1") to a machine_type before create_scene. FORM-/FRM codes are SLA (auto_layout); FS/PILK/FUSX codes are SLS (auto_pack). Families PreFormServer accepts but does not list yet (the Fuse X1 in 3.63) carry an unlisted note.
Inputs: no named parameters.
list_scenesARead-only
List every scene PreFormServer currently holds in memory.
Inputs: no named parameters.
load_formA
Open an existing .form file as a new scene. file must be an absolute path. Returns the scene.
Inputs: file (required).
loginA
Log in to Formlabs Web Services for remote printing, Fleet Control and Dashboard printers. Credentials never pass through the conversation: set FORMLABS_USERNAME and FORMLABS_PASSWORD (or FORMLABS_ACCESS_TOKEN) in the MCP server's environment and call this tool with no arguments.
Inputs: no named parameters.
logoutA
Log out of Formlabs Web Services.
Inputs: no named parameters.
pack_and_cageA
Pack models and build a printed cage around them so they stay together after SLS printing. SLS only; acts on the most recently created scene. packing_type is PACK_VOLUME (default), PACK_HEIGHT, PACK_NORMAL or PACK_NONE. Returns the scene.
Inputs: models, cage_label, packing_type, model_spacing_mm.
preform_statusARead-only
Report how this MCP server is set up without touching PreFormServer: whether PreFormServer is installed and where, its version, local or remote mode, allowed directories, and how file paths are rewritten for a Wine-hosted PreFormServer (path_style, path_map). Use it to diagnose setup problems before health_check.
Inputs: no named parameters.
print_to_printerADestructive
Upload the scene to a printer and queue it, or start it. Confirm with the user first. printer is a printer serial name (e.g. "Fuse-Loud-Otter"), a local IP address, a Fleet Control queue id (requires login), or a built-in virtual printer id such as "Form 4" for a dry run without hardware. print_now=true starts immediately if the printer is ready; otherwise the job waits in the queue. Returns job_id.
Inputs: printer (required), job_name (required), scene_id, print_now, +1 more.
replace_modelA
Swap a model's mesh for a new file while keeping its placement and supports. Useful when the user re-exports a revised part. file must be an absolute path.
Inputs: file (required), model_id (required), scene_id, repair_behavior.
save_formADestructive
Save the scene as a .form file at an absolute path. Overwrites silently, so confirm with the user first if the file already exists.
Inputs: file (required), scene_id.
save_fps_fileADestructive
Export the scene's print settings to a .fps file for reuse with create_scene.
Inputs: file (required), scene_id.
save_screenshotBDestructive
Render the scene to a .png or .webp at an absolute path. view_type is ZOOM_ON_MODELS, FULL_BUILD_VOLUME or FULL_PLATFORM_WIDTH.
Inputs: file (required), yaw, pitch, scene_id, +2 more.
update_modelA
Move, rotate, rescale, rename or lock a model. position is {x,y,z} mm; orientation is Euler degrees {x,y,z}. lock (FREE, LOCKED_XY_ROTATION_FREE_TRANSLATION, LOCKED_ROTATION_FREE_TRANSLATION, FULLY_LOCKED) controls what auto_layout / auto_pack may change.
Inputs: model_id (required), lock, name, scale, +3 more.
update_sceneA
Change a scene's printer, material, layer thickness or print setting while keeping its models.
Inputs: scene_id, machine_type, material_code, print_setting, +1 more.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 45 tools
Most tools have clearly distinct purposes, and the descriptions carefully separate the tricky families (auto_layout/auto_pack/fill_build_platform/fill_build_chamber by SLA vs SLS, add_drain_holes vs auto_add_drain_holes). However get_print_validation overlaps with the detect_cups/detect_minima/detect_supportedness trio, and health_check vs preform_status are both diagnostics, so a few boundaries blur.
Nearly everything follows a snake_case verb_noun pattern (create_scene, delete_model, auto_layout, detect_cups, print_to_printer) with a consistent auto_ prefix for automation tools. Minor deviations like health_check, preform_status, login/logout are acceptable and still readable.
45 tools is very heavy, well past the point where an agent can comfortably scan the surface. While the domain (scene lifecycle, model editing, validation, printing, auth, setup) is genuinely broad, the suite is close to the extreme end and several tools could plausibly be consolidated.
The surface covers a full lifecycle: scene create/get/update/delete, model import/get/update/duplicate/replace/delete, positions and supports, validation and interference checks, save/export/screenshot, printer discovery and job submission, materials, and auth. No obvious dead ends for the stated purpose.
Maintenance
Related MCP Connectors
A Model Context Protocol server for Wix AI tools
A comprehensive Model Context Protocol (MCP) server that enables AI assistants to interact with yo…
Enable secure connectivity between Sentry issues and debugging data, and LLM clients, using a Model Context Protocol (MCP) server.
Model Context Protocol server for the Apideck Unified API. Connect any MCP-compatible agent framework to 100+ accounting systems, HRIS platforms, file storage providers, and more through one integration. More information https://www.apideck.com/mcp-server
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceA Model Context Protocol server that allows AI assistants to search for, explore, and retrieve 3D printable models from Thingiverse.7MIT
- FlicenseNot gradedqualityDmaintenanceA demonstration implementation of the Model Context Protocol server that facilitates communication between AI models and external tools while maintaining context awareness.-
- AlicenseNot gradedqualityCmaintenanceA server that integrates Blender with local AI models via the Model Context Protocol, allowing users to control Blender using natural language prompts for 3D modeling tasks.123MIT
- AlicenseNot gradedqualityDmaintenanceA server that implements the Model Context Protocol, providing a standardized way to connect AI models to different data sources and tools.12 npm12MIT