# orcaslicer-mcp [Health: Active]

**Category:** 🏭 Industrial & IoT  
**Repository:** https://github.com/MaxEllis/orcaslicer-mcp  
**GitHub Stars:** 55  
**Views:** 2  
**Installs:** 0  
**Upvotes:** 0  
**Directory Page:** https://allmcps.com/mcp/orcaslicer-mcp

## Description
Drive a running OrcaSlicer with AI: load models, tune settings, slice, and analyze results

## Tools
Capabilities this server exposes over MCP:

- **get_status** — Snapshot of the current OrcaSlicer session: app and project info, the active
    print/filament/printer presets with which of their keys are modified (dirty), whether the
    last slice is still valid, and whether a slice is running. Read-only.

    Call it first to orient before slicing or editing, to see which settings drift from their
    preset, or to check slice_result_valid before trusting earlier stats.
- **get_config** — Read merged config values (optionally filtered to `keys`).
- **set_config** — Apply config changes to the active project as unsaved overrides, atomically: if any
    key is invalid the whole batch is rejected and nothing changes. Returns {applied, errors}.

    Overrides show as modified in get_status, are not written to any preset file, and revert
    if the preset is reselected; call save_preset to persist them. Each apply invalidates the
    last slice, so re-slice afterwards. It does not run the physics gate, so for temperature,
    speed, acceleration, or flow keys run check_profile_physics before trusting the result. To
    edit a stored preset rather than the live project, use edit_preset.
- **slice** — Start slicing the current plate in the background and return immediately, without waiting
    for the result. The reply is 'started' (a slice began), 'already_valid' (the plate is
    unchanged and the last result still holds), or a conflict if a slice is already running.

    Fire-and-forget: poll get_slice_status for progress and stats, or cancel_slice to stop it.
    Prefer slice_and_wait when you want the finished stats back in one call.
- **get_slice_status** — State of the current or most recent slice: state (slicing, done, error, or idle), stats
    (print time and filament use when done), and any warnings or errors. Read-only.

    Poll this after slice to follow progress and read the result; 'idle' means no slice has run
    or it was cancelled. For only the pass/fail warnings use get_slice_warnings; for a
    per-feature time and filament breakdown use get_slice_breakdown.
- **get_slice_warnings** — Just the warnings/errors from the last (or current) slice, plus validity - the
    fast 'did anything go wrong' check and the way to confirm a fix cleared.

    NOTE: only as complete as the API exposes. On the current fork build this may report
    valid with an empty warnings list even when the GUI shows a plate-boundary toast -
    the fork must populate the plater warning list (tracked as the fork batch). Once it
    does, this reports the real warnings with no change here.
- **get_slice_breakdown** — Per-feature breakdown of the last slice + a stateless predicted-vs-observed flow check.

    Returns per-role time/filament + speed/flow ranges, global time-weighted metric
    distributions, per-layer aggregates, and a prediction_check flagging where the profile's
    speed was silently throttled at the flow ceiling ('clamped'). Answers 'which feature is
    the time hog' directly instead of by trial slicing.

    Degrades to {"available": false, "reason": ...} on fork builds that don't emit the
    breakdown, or when there is no valid slice.
- **cancel_slice** — Abort a running slice, or unwedge a stale 'slicing' state (e.g. after an
    object outside the bed). Safe when idle.
- **slice_and_wait** — Slice the current plate and block until it finishes, then return the final stats and
    warnings in one call. If the plate is already sliced and unchanged, it returns the existing
    result without re-slicing.

    This is the usual way to slice when you want the outcome immediately. For a non-blocking
    start, use slice then poll get_slice_status; to sweep one setting across values, use
    compare_settings.
- **apply_and_slice** — Apply config overrides and then slice in one step, returning {applied, errors, result}
    with the resulting stats and warnings. The changes are atomic (any invalid key rejects the
    whole batch) and unsaved, exactly like set_config, so they revert if the preset is reselected.

    Use this to test the effect of a tweak in a single call. Use set_config then slice_and_wait
    to keep the steps separate, or compare_settings to try several values of one key.
- **compare_settings** — For each value of `key`, slice and collect stats/warnings; restore the original when done.

    Non-destructive: the original value of `key` is put back even on error.
    
- **compare_slices** — Slice the current plate under several named variants and compare the cost of each.

    Each variant is {"name": str, "changes": {setting: value}}; changes={} means the
    current config as-is (a natural baseline row). Applies each variant over the ORIGINAL
    config (resetting between variants, so they don't stack), slices it, then restores your
    config exactly as it was - nothing is left changed (slice validity is left false, as
    after any un-resliced edit).

    Returns a ready-to-relay `headline` and `table_markdown`, plus structured `variants`.
    All deltas and percentages are ALREADY computed and rounded against `baseline`
    (defaults to the changes={} variant, else the first) - relay them as given rather than
    recomputing. `recommended` names one pick; `recommended_is_dominant` says whether it
    beats every variant on every axis (time, filament, warnings) or is only the fastest
    warning-free option amid a genuine trade-off (`tradeoff` then names the frontier).

    Each variant is a full slice (minutes); capped at 8. Set detail=True only when a
    per-feature (wall/infill/support) split is wanted - it grows the response ~N x. With
    more than ~5 variants, lead with the recommendation and the extremes, not all rows.
    
- **list_objects** — List objects on the current plate: id (stable), name, size_mm, and transform (offset/rotation/scale).
- **set_object_config** — Set per-object config overrides on an object by id, e.g. {"wall_loops": 4, "sparse_infill_density": "30%"}. Atomic (nothing applied if any key is invalid).
- **duplicate_object** — Duplicate an object on the plate by id (adds a copy, offset from the original).
- **delete_object** — Remove one object from the current plate by id. This is permanent within the session
    and cannot be undone through the API; the other objects keep their ids.

    Call list_objects first to get the id. Deleting leaves the last slice invalid, so re-slice
    afterwards. To drop just one copy made with duplicate_object, pass that copy's id.
- **transform_object** — Move/rotate/scale an object by id. translate=[dx,dy,dz] mm (relative), rotate=[rx,ry,rz] degrees (relative), scale=[sx,sy,sz] absolute factor. Provide at least one.
- **arrange_plate** — Auto-arrange all objects on the plate (async job; poll get_job_status until idle).
- **auto_orient** — Auto-orient all objects for printing (async job; poll get_job_status until idle).
- **get_job_status** — Whether the plate's background job worker is idle or still running. Read-only.

    arrange_plate and auto_orient start async jobs; poll this until it reports idle before you
    read object positions or slice, so you act on the settled layout rather than a mid-move
    state.
- **watch_events** — Collect live events (slice.*/config.changed/project.opened) over a bounded window.
- **find_config_keys** — Find config keys containing `substring` (helps discover among the ~600 keys).
- **diagnose_plate** — One-call plate diagnosis: app/slice status, objects on the plate, bed + active
    skirt/brim/clearance settings, and the last slice's warnings - so you don't have to
    chain status->objects->config. Start here for 'why won't this slice / fit'.

    Slice warnings are only as complete as the fork exposes today (see get_slice_warnings).
    For a 'does it fit the bed' estimate, pair with check_placement.
- **check_placement** — Estimate whether every object (plus its skirt/brim ring) fits inside the printable
    area. Returns per-object fit, expanded first-layer bbox, per-edge clearance (mm), and
    overflow.

    APPROXIMATE: uses the object footprint from size+offset, not the sliced toolpath (skirt
    arcs, half-line-width, travel/wipe excluded); single-instance objects only. At ~mm
    margins the true verdict needs get_slice_warnings - this is a fast first-pass.
- **consult** — Retrieve curated slicing knowledge + saved context notes for a topic,
    symptom, or intent. ALWAYS call before deriving or changing settings for
    a user goal. Composes principles per situation - never returns preset
    bundles. Falls back to find_config_keys/web search if empty.

    When recommending, present 2-3 concrete options quantified with
    predicted print time and filament mass from real slice results (slice +
    status tools) - never adjectives alone.
- **check_profile_physics** — Deterministic pre-save gate: fetches the live config, overlays optional
    proposed `changes`, and runs flow/temperature/geometry/cooling math.
    RUN THIS BEFORE save_preset. verdict=blocked means DO NOT SAVE.
- **remember** — Persist a context fact for future sessions. scope: 'machine:<printer>/<filament>',
    'user', or 'project:<name>'. Local plain files; user-readable and deletable.
- **describe_setting** — Authoritative definition of one OrcaSlicer setting: label, tooltip, type, unit, valid
    range, enum values, and default. Read-only and offline, so it works even when OrcaSlicer is
    not running.

    Use it to learn a setting's exact type and allowed values before writing it with set_config
    or edit_preset. To find candidate keys by keyword first, use search_settings.
- **search_settings** — Search settings by keyword across key/label/tooltip; returns compact matches (key, label, category, short tooltip), ranked key/label first. Offline.
- **load_model** — Load a model file (path on the OrcaSlicer host) onto the current plate.
    Accepts .stl/.obj/.3mf, plus .step/.stp on fork v2.3.2-mcp.3+. Large STEP files
    can take a minute to tessellate; the call waits.
- **select_preset** — Make the named preset the active one for its group (print, filament, or printer).

    Selecting a preset discards unsaved set_config overrides and reverts settings to the
    preset's stored values, so it is also the canonical way to reset dirty config; it leaves
    the last slice invalid, so re-slice afterwards. Use list_presets for valid names, and
    save_preset first if unsaved edits should survive the switch.
- **save_preset** — Save the currently edited settings as a named user preset (create or update,
    visible in the GUI immediately). type = print|filament|printer. detach=True saves
    it standalone instead of inheriting the current base preset; use it when creating a
    filament preset for a DIFFERENT material than the one selected, otherwise the new
    preset inherits the base's filament_type and temperatures.

    Run check_profile_physics first; do not save when verdict=blocked.
- **list_presets** — List print/filament/printer presets with system/selected/visible flags.

    F12: by default returns only USER presets plus whatever is currently SELECTED -
    the built-in system presets are ~400 entries of noise. Pass include_system=True
    for the full list, and/or type='print'|'filament'|'printer' to restrict to one
    category. `hidden_system` reports how many system presets were filtered out.
- **set_layer_height** — Variable layer height for one object. mode='adaptive' (quality 0..1, higher = finer
    detail) generates an adaptive profile; mode='reset' (aliases: 'default', 'none')
    restores uniform layers.
- **set_height_range** — Override the layer height over a Z band of one object (e.g. 0 to 5 mm printed at 0.1 mm
    for finer detail near the base). Passing the same min_z and max_z again updates that band's
    height; clear=True removes every band on the object.

    Bands are per-object and invalidate the last slice, so re-slice afterwards. For a single
    height across the whole object use set_layer_height instead. Get the id from list_objects.
- **get_preset_config** — Read the full settings of a named preset without selecting it.
    type = print|filament|printer.
- **delete_preset** — Delete a USER preset (system presets and the currently-selected one are refused).
    type = print|filament|printer.
- **edit_preset** — Edit a named preset's settings and persist them: selects it, applies the
    changes atomically, saves under the same name. Runs the check_profile_physics
    gate first (F15) and refuses with error=physics_blocked if the changes would
    INTRODUCE a failing physics check (pre-existing failures do not block
    unrelated edits). For type='filament', checks that also depend on the currently
    selected PRINT preset (flow_ceiling, temp_vs_flow) do not block; they come back
    as cross_layer_warnings, because a filament preset pairs with many print presets.
- **rename_preset** — Rename a user preset by copying it to new_name, selecting the copy, and deleting the
    original. Only user presets can be renamed; system presets are read-only.

    Because it selects the renamed preset, this leaves it active and discards unsaved config
    overrides, the same as select_preset, and leaves the last slice invalid, so re-slice
    afterwards.
- **get_gcode** — Retrieve the last successful slice's G-code as text.
- **describe_plate** — Machine-readable plate facts from the last slice's G-code, per object, so you can answer
    orientation and placement questions instead of guessing from Euler angles or a picture:
    how the part stands (flat / tilted / on an edge or corner, from first-layer contact versus its
    widest layer), the first-layer footprint as islands, where overhang extrusions concentrate by
    10 mm height band, where support stands and where its interface touches the part, and which
    side the outer-wall seams sit on (checked against seam_position). Each object gets a
    server-written summary sentence; relay it rather than recomputing. Read-only. Needs a valid
    slice; returns {"error": "not_sliced"} otherwise. Copies of one object are aggregated (Orca
    labels every copy 0); footprint islands still show per-copy contact. The parsed result is
    cached per slice (the G-code itself is still downloaded each call to detect a new slice).
    All bboxes are [x0, y0, x1, y1] in plate millimetres.
- **save_gcode** — Save the last successful slice's G-code and record the slice (model, geometry, full
    settings snapshot) under that filename, so that when klipper-mcp later prints this exact
    file the real outcome joins back to these settings. Returns the saved path; hand it to
    klipper-mcp's start_print. Default filename: <object>_<timestamp>.gcode. Never overwrites
    an existing file — a name collision gets a -2, -3, ... suffix. Writes into a gcode folder
    under PRINT_OUTCOMES_DIR if set, else under the shared print-outcomes folder
    (~/projects/_shared/print-outcomes) if it already exists, else under ~/.orcaslicer-mcp;
    the gcode folder itself is created if missing. If the shared outcome store is not present,
    or the store write fails, the file is still saved and outcome_recorded is False.
- **recall_prints** — How did past prints of THIS model actually turn out? Matches the current plate by geometry
    (or by model_name if given / the slicer is offline), returning each past print's result
    (success/cancelled/error), your recorded verdict (e.g. 'warped'), and the settings it was sliced
    with. Call this BEFORE slicing and tell the user anything relevant (a past warp, a failed layer
    height). Read-only. Returns available=false and nothing else when no outcome store exists.
    If neither geometry nor name matches, it returns the most recent prints of ANY model with
    matched_by='recent'; never attribute those to the current model.
- **render_plate** — Render a PNG picture of the current plate so you can SEE it.

    view="editor": the models on the bed BEFORE slicing - use to check
    orientation, plate contact, and first-layer footprint (an Euler triple is
    near-unreadable; this is the ground truth). view="preview": the sliced
    toolpaths colored by feature role AFTER a successful slice - support is
    visibly distinct, so use it to check where support actually went.
    angle: iso|top|front|left|right|rear|bottom.
    frame: "plate" zooms out to the whole bed (where the part sits, footprint),
    "object" zooms in on the model/toolpaths (detail). Defaults to "plate" for
    the editor view and "object" for the preview view; pass it explicitly when
    a side view of a small part would otherwise be a speck on a big bed.
    

## Claude Desktop Quick Installation
Install path detected from listing signals. Uses `uvx` (confidence: high):

```json
"mcpServers": {
  "orcaslicer-mcp": {
    "command": "uvx",
    "args": ["orcaslicer-mcp"]
  }
}
```

## Documentation & README

# OrcaSlicer MCP

[![PyPI](https://img.shields.io/pypi/v/orcaslicer-mcp)](https://pypi.org/project/orcaslicer-mcp/)
[![Python](https://img.shields.io/pypi/pyversions/orcaslicer-mcp)](https://pypi.org/project/orcaslicer-mcp/)
[![License](https://img.shields.io/badge/license-AGPL--3.0-blue)](LICENSE)
[![MCP Badge](https://lobehub.com/badge/mcp/maxellis-orcaslicer-mcp)](https://lobehub.com/mcp/maxellis-orcaslicer-mcp)
[![Buy Me a Coffee](https://img.shields.io/badge/support-buy%20me%20a%20coffee-ffdd00)](https://buymeacoffee.com/maxellis)

Let Claude work alongside you in a real, running OrcaSlicer. It loads models, arranges the plate, tunes settings, slices, and reads the result back as numbers you can question: which feature ate the print time, what a setting actually does, whether a profile breaks your printer's physics. Every change lands in the GUI while you watch, so the slicer stays yours and you get better at it as you go.

This package is an [MCP](https://modelcontextprotocol.io) server: it bundles no model and talks to nothing but OrcaSlicer, at an address you configure, localhost by default. The model comes from your MCP client. If that client uses a hosted one, your conversation goes there as any chat does; your models, profiles, and gcode stay on the machine running the slicer. Point the client at a local model and nothing leaves at all.

## What it can do

### Knowing what the settings mean

An offline settings reference ships with the package, carrying the authoritative label, tooltip, type, range, enum, and default for each key, so `describe_setting`, `search_settings`, and `compare_settings` answer from OrcaSlicer's own source instead of guessing. `consult` composes curated slicing knowledge and your saved notes by topic, symptom, or goal.

`check_profile_physics` is a deterministic gate. It overlays proposed changes on the live config, runs flow, temperature, geometry, and cooling math, then returns `ok`, `warnings`, or `blocked`. Accelerations your printer cannot reach and speeds past the flow ceiling get caught before they reach a print.

### Settings

Read and write any of roughly 800 OrcaSlicer settings on the live config, for the whole plate or scoped narrower: `get_config`, `set_config`, `find_config_keys`, `set_layer_height`, `set_height_range` for a band of layers, and `set_object_config` for one object's overrides.

### Presets

`list_presets`, `select_preset`, `get_preset_config`, `edit_preset`, `save_preset`, `rename_preset`, `delete_preset`.

### Slicing, and reading the result back

`slice`, `slice_and_wait`, `apply_and_slice`, `cancel_slice`, `get_slice_status`, `get_slice_warnings`, `get_gcode`.

`get_slice_breakdown` returns per-feature time, filament, and flow. OrcaSlicer shows the same information in the legend beside its preview, sized for a screen; this returns it as numbers an assistant can compare and act on:

```
role                    time      share   filament   mean flow
inner_wall              5m 41s    30.8%     6.43 g    16.0 mm3/s
outer_wall              3m 19s    18.0%     3.20 g    13.6 mm3/s
sparse_infill           3m 07s    17.0%     3.57 g    17.0 mm3/s
internal_solid_infill   2m 01s    11.0%     1.72 g    11.8 mm3/s
bridge                     52s     4.7%     0.26 g     4.4 mm3/s
support_interface          36s     3.2%     0.52 g    12.3 mm3/s
overhang_perimeter         28s     2.5%     0.13 g     3.7 mm3/s
internal_bridge            21s     1.9%     0.45 g    19.9 mm3/s
top_surface                19s     1.7%     0.29 g    12.5 mm3/s
brim                       12s     1.1%     0.21 g    14.7 mm3/s
bottom_surface              7s     0.7%     0.10 g    11.8 mm3/s
                        18m 24s            16.89 g
```

It answers which feature is eating the time without slicing repeatedly to find out. A `prediction_check` rides along and flags any role where the profile's requested speed got throttled at the flow ceiling.

`compare_slices` slices the current plate under several named variants and returns one comparison, so "what does layer height actually cost me?" is a single question rather than four manual slices. It applies each variant over your original config, restores it when done, and hands back a verdict plus a table with every delta already worked out:

```
Recommended: 0.4mm - fastest with no warnings.

variant     time      filament   vs 0.4mm (baseline)
0.3mm       8h 10m    41.0 g      +1h 30m (+22%), -7.0 g (-15%)
0.4mm  *    6h 40m    48.0 g      baseline
0.5mm       5h 20m    53.4 g      -1h 20m (-20%), +5.4 g (+11%)
0.6mm       4h 35m    57.1 g      -2h 05m (-31%), +9.1 g (+19%)  thin-wall warning
```

It only crowns a winner when one variant genuinely beats the rest on time, filament, and warnings; when they trade off, it names the fastest, the lightest, and where the warnings landed, and leaves the choice in front of you. Pass `detail=True` for the per-feature split of each variant.

### Models and the plate

`load_model` (`.stl`, `.obj`, `.3mf`, plus `.step` and `.stp` on fork v2.3.2-mcp.3 and later), `list_objects` with each object's world-space bounding box and an `on_plate` flag, `transform_object`, `duplicate_object`, `delete_object`, `arrange_plate`, `auto_orient`, `check_placement`, `diagnose_plate`, `get_job_status`.

### Plate renders

`render_plate` hands back a PNG, so the assistant can look instead of inferring from coordinates. A rotation reads instantly as a picture and barely at all as three Euler angles. Seven camera angles cover `iso`, `top`, `front`, `left`, `right`, `rear`, and `bottom`. Use `frame="plate"` to stand back for the whole bed, or `frame="object"` to lean in on the part. Requires fork v2.3.2-mcp.4 or later.

| `view="editor"` | `view="preview"` |
|---|---|
| ![A press-fit tube connector sitting on the bed](https://raw.githubusercontent.com/MaxEllis/orcaslicer-mcp/HEAD/docs/images/conn-editor.png) | ![The same part sliced, toolpaths coloured by feature role](https://raw.githubusercontent.com/MaxEllis/orcaslicer-mcp/HEAD/docs/images/conn-preview.png) |
| Your models on the bed. Answers orientation, plate contact, and first-layer footprint. | Sliced toolpaths coloured by feature role, so support placement is plain to see. |

`describe_plate` answers the same questions as numbers and one sentence per object, computed from the sliced G-code: how the part stands (flat, tilted, or on an edge or corner, from first-layer contact against its widest layer), the first-layer footprint as islands, where overhang extrusions concentrate by height band, where support stands and where it touches the part, and which side the seams sit on, checked against `seam_position`. It exists because an assistant reads a sentence more reliably than a picture. Copies of an object are aggregated; the islands still show each copy's contact patch. On a plate of three tilted connector copies it reads: "Body4.stl (3 copies) stands on an edge or corner: first-layer contact is 5% of its widest layer, in 3 islands of about 50 mm2 each. Overhang extrusions concentrate at Z 0 to 10 mm. Support is present from Z 0.4 to 56.8 mm, standing in 3 places and touching the part in 7 zones. Seams align on the +Y side (91%), matching seam_position=back."

### Live state and memory

`get_status` and `watch_events` report what the slicer is doing now. `remember` persists machine, user, and project facts for later sessions, as plain local files in `~/.orcaslicer-mcp/notes/`, relocatable with `ORCA_MCP_NOTES_DIR`.

### Learning from real prints

`save_gcode` saves the last successful slice's G-code and records the model, geometry, and full settings snapshot that produced it. Set `PRINT_OUTCOMES_DIR` to say exactly where; otherwise it writes into the shared print-outcomes folder (`~/projects/_shared/print-outcomes/`) if that folder already exists on this machine, and into `~/.orcaslicer-mcp/` (the same folder `remember` uses) if it does not. `recall_prints` reads the shared folder before you slice, so the assistant can say how past prints of this model actually went: success, cancelled, or the verdict you gave it, and the settings used.

Recording and recall both depend on a companion service, the [klipper-mcp](https://github.com/MaxEllis/klipper-mcp) server, whose `klipper-mcp-capture` process writes the real print result into the same store once your printer finishes the job, and whose `start_print` tool uploads the file `save_gcode` saved under the same filename. Without that companion, `save_gcode` still writes the G-code file (its folder is created on first use even so) but records nothing, and `recall_prints` returns `available: false` and does nothing else. Neither tool makes the server contact you on its own; the assistant only sees new outcomes when it calls `recall_prints` again in a later session.

## What you need

Stock OrcaSlicer ships without a control API, so a matching build does that half of the job.

1. **The OrcaSlicer MCP build.** OrcaSlicer 2.3.2 with an embedded local API, token-authenticated and bound to localhost until you say otherwise. Get it from the [releases page](https://github.com/MaxEllis/OrcaSlicer/releases). If no binary is up for your platform yet, build the `remote-api` branch from source.
2. **This package (`orcaslicer-mcp`).** The MCP server that connects your AI client to that build.

> **Updating:** take new builds from the [releases page](https://github.com/MaxEllis/OrcaSlicer/releases), never from inside the app. The in-app updater offers *stock* OrcaSlicer, which drops the control API. Builds mcp.2 and later turn that updater off for you. On an older build, click **Skip this Version** if a "new version available" prompt appears.

## Quickstart

Install [uv](https://docs.astral.sh/uv/getting-started/installation/) first, because it provides the `uvx` command that runs the server. One line does it: `curl -LsSf https://astral.sh/uv/install.sh | sh` on macOS and Linux, or `irm https://astral.sh/uv/install.ps1 | iex` in PowerShell on Windows.

1. Install the OrcaSlicer MCP build, launch it, and finish the one-time setup by picking your printer. A fresh install may show a **“Bambu Network Plug-in Required”** dialog. Click **Skip for Now**, since that plug-in only serves Bambu cloud printing. The control API starts once setup is finished.
2. Open **Preferences** (Ctrl+P), go to **Remote API**, and tick **Enable Remote API**. Copy the token shown on that page. Access stays localhost-only unless you also switch on "Allow LAN access".
3. Connect your MCP client.

    **Claude Desktop:** download `orcaslicer-mcp-<version>.mcpb` from the [releases page](https://github.com/MaxEllis/orcaslicer-mcp/releases/latest) and open the file. Claude Desktop offers to install it. Open the extension's settings afterwards, paste the token from step 2, and enable it.

    > Ignore any guide that tells you to hand-edit `claude_desktop_config.json`. Current Claude Desktop builds rewrite that file themselves and drop added `mcpServers` entries, so the edit will not stick. The extension leaves the file alone and finds `uvx` by itself.

    **Claude Code and other MCP clients:** add the server to your client's MCP config. For Claude Code that means a project `.mcp.json`:

    ```json
    {
      "mcpServers": {
        "orcaslicer": {
          "command": "uvx",
          "args": ["orcaslicer-mcp"],
          "env": {
            "ORCA_API_TOKEN": "<token from Preferences>"
          }
        }
      }
    }
    ```

    `ORCA_API_URL` defaults to `http://127.0.0.1:13130`. Set it only if you changed the port, or if OrcaSlicer runs on another machine with LAN access enabled there.

    > **Windows note:** if `uvx orcaslicer-mcp` fails with *"The process cannot access the file because it is being used by another process"* while installing `pywin32`, Windows Search or Defender grabbed a freshly written file mid-install (uv does not retry). Use a pip-based fallback, which does retry, and point `"command"` at the resulting exe:
    >
    > ```powershell
    > python -m venv "$env:USERPROFILE\.venvs\orcaslicer-mcp"
    > & "$env:USERPROFILE\.venvs\orcaslicer-mcp\Scripts\python" -m pip install orcaslicer-mcp
    > ```
    >
    > Then set `"command"` to `C:\Users\<you>\.venvs\orcaslicer-mcp\Scripts\orcaslicer-mcp.exe` with no `args`. Upgrade later with the same pip command plus `-U`.

    > **macOS note for GUI clients other than Claude Desktop:** apps launched from the Dock do not inherit your terminal's PATH, so `"command": "uvx"` can fail silently. Run `which uvx` in Terminal, then paste the full path it prints into `"command"`. It is usually `~/.local/bin/uvx`.

4. Restart your client and ask: *"Load benchy.stl, slice it with the current profile, and tell me the print time."*

## Security

- The control API binds **127.0.0.1 only** by default. LAN access is an explicit opt-in in Preferences.
- Every request must carry the API token. OrcaSlicer generates it on first run and can regenerate it at any time.
- The MCP server runs as a local stdio process and opens no connection except to OrcaSlicer. No telemetry.

## Development

```bash
uv venv && uv pip install -e ".[dev]"
uv run pytest   # unit tests against a mock API, plus a guarded live smoke test
```

The live smoke test skips itself unless `ORCA_API_URL` and `ORCA_API_TOKEN` point at a running OrcaSlicer MCP build.

Protocol notes, design specs, and verification results live in [`docs/`](https://github.com/MaxEllis/orcaslicer-mcp/blob/HEAD/docs/).

## Privacy policy

The server talks to OrcaSlicer's local API at the address you configure, localhost by default, and to nothing else. It has no backend, so there is no service of ours for anything to reach. What leaves your machine is whatever your MCP client sends its model: the conversation, plus any settings or file contents you or the assistant put into it. Their terms govern that traffic, and it is the same traffic any other use of that client produces. A local model removes it entirely.

- **Data collection:** none. The server collects nothing about you or your usage.
- **Usage and storage:** models, settings, and gcode stay on the computer running OrcaSlicer, held in memory only for the duration of each request. The API token authenticates the server to OrcaSlicer, and your MCP client stores it. Claude Desktop keeps extension settings in the operating system's credential store.
- **Third-party sharing:** none by this server, which has no analytics and no backend. Traffic between your client and its model provider sits outside this project and falls under their policies.
- **Data retention:** the only data written to disk is notes you save yourself with `remember`, stored as plain files under `~/.orcaslicer-mcp/notes/`, and the G-code plus slice records that `save_gcode` writes: under `~/projects/_shared/print-outcomes/` when that shared folder already exists, otherwise under `~/.orcaslicer-mcp/` (either relocatable with `PRINT_OUTCOMES_DIR`), read back by `recall_prints` and joined with real print results by the separate klipper-mcp project. Read or delete either folder whenever you like. Delete them and nothing remains.
- **Contact:** questions and concerns go in [an issue](https://github.com/MaxEllis/orcaslicer-mcp/issues).

## Status

Early public release, soft launch. The server carries 183 unit tests and gets exercised on real print jobs. Prebuilt OrcaSlicer MCP builds cover Windows, macOS, and Linux on the [releases page](https://github.com/MaxEllis/OrcaSlicer/releases). Issues and reports are welcome.

## Support

The project is free and stays that way. If it saves you time and you feel like saying thanks, you can buy me a coffee.

<a href="https://buymeacoffee.com/maxellis"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me a Coffee" height="50"></a>

## License

AGPL-3.0, matching OrcaSlicer, from whose source the bundled settings schema derives. See [LICENSE](https://github.com/MaxEllis/orcaslicer-mcp/blob/HEAD/LICENSE).

<!-- mcp-name: io.github.MaxEllis/orcaslicer-mcp -->

