Skip to main content
Glama
3D Print Recovery Assistant MCP Server

3D Print Recovery Assistant MCP Server

3D Print Recovery Assistant: MCP Server

CMU 24-679 (Automated Science), Homework 5, Question 4.

This is a local Model Context Protocol server. It exposes five read-only tools for deciding what to do about a failing or failed FDM 3D print. Tools 1–3 come unchanged from Homework 4. Tools 4–5 are new.

#

Tool

Question it answers

Origin

1

check_functional_geometry

Does the container still hold the required volume?

HW4

2

check_recovery_feasibility

Can the remaining layers absorb the contour correction?

HW4

3

expected_recovery_savings

Does trying to recover save time and filament on average?

HW4

4

early_stop_trend_alarm

While printing: should I stop now (OK / WATCH / STOP), and what would stopping save?

new

5

layer_shift_strength_check

After a layer shift: does the part still carry its load?

new

The server runs locally over stdio and makes no network calls. It never sends commands to a printer.

Setup

You need Python 3.10 or later. Node 22 or later is only needed for MCP Inspector.

git clone https://github.com/ishaanamahajan/print-recovery-mcp.git
cd print-recovery-mcp
python3 -m venv .venv
.venv/bin/pip install -r requirements.txt
.venv/bin/python -m pytest -q          # 20 tests, including hand-calculation checks

Related MCP server: fabtally-mcp

Connect a client

MCP Inspector (GUI)

npx @modelcontextprotocol/inspector .venv/bin/python server.py

MCP Inspector (CLI, reproduces the demo)

bash demo/run_inspector_demo.sh        # writes demo/inspector_transcript.md

Claude Code

claude mcp add print-recovery -- "$PWD/.venv/bin/python" "$PWD/server.py"

Claude Desktop. Add this to claude_desktop_config.json, using absolute paths:

{ "mcpServers": { "print-recovery": {
    "command": "/ABS/PATH/print-recovery-mcp/.venv/bin/python",
    "args": ["/ABS/PATH/print-recovery-mcp/server.py"] } } }

Apple Silicon with an x86_64 (Rosetta) Node. Clients built on Node launch Python under the same architecture as Node. The arm64 pydantic_core then fails to load and the client reports "Connection closed". To fix it, launch with arch -arm64 /path/.venv/bin/python server.py (the demo script does this automatically) or install an arm64 Node.

Tool contracts

All five tools follow the same rules.

  • Inputs. Each tool has a JSON Schema in which every number carries a minimum and maximum and a unit in both its name and its description. The client sees these ranges before it calls.

  • Results. Each tool has an outputSchema. A call returns structuredContent (typed JSON) plus the same JSON as text.

  • Annotations. Every tool is marked readOnlyHint: true, destructiveHint: false, idempotentHint: true and openWorldHint: false.

  • Invalid inputs. No partial result is ever returned. The server rejects bad input in one of two layers, and both return isError: true with a message naming the field:

    1. Schema layer (pydantic). Wrong types, out-of-range values and lists that are too short are rejected before the tool runs. Example: success_probability = 80 gives "Input should be less than or equal to 1".

    2. Domain layer (the tool's own checks). These catch rules that involve more than one input, such as wall thickness ≥ radius, mismatched list lengths, layers not increasing, the last measured layer past the end of the print, or no load given. They are raised as ToolError("Invalid input: …").

1. check_functional_geometry (HW4)

$V = \pi (r-t)^2 (H-b) / 1000$ mL

Input

Unit

Range

outer_radius_mm

mm

1–500

wall_thickness_mm

mm

0.4–50, < radius

height_mm

mm

1–1000

base_thickness_mm

mm

0.2–100, < height

min_capacity_mL

mL

0–10⁶

  • Result: estimated_capacity_mL, margin_mL, meets_requirement.

  • Limitation: assumes an ideal cylinder filled to the brim. Capacity does not prove the container is watertight.

2. check_recovery_feasibility (HW4)

$N_{req} = \lceil c/\Delta_{max} \rceil$, and recovery is feasible if $N_{req} \le N_{rem}$.

Input

Unit

Range

correction_mm

mm

0–50

max_correction_per_layer_mm

mm/layer

0.01–2

remaining_layers

layers

integer, 0–100,000

layer_height_mm

mm

0.04–1.0

  • Result: required_layers, transition_height_mm, spare_layers, feasible.

  • Limitation: $\Delta_{max}$ is an assumed value, not a measured capability of the printer.

3. expected_recovery_savings (HW4)

$E[T] = T_{int} + T_{rec} + (1-p)T_{restart}$ and $E[F] = F_{rec} + (1-p)F_{restart}$.

Input

Unit

Range

restart_time_h

h

0.01–1000

recovery_time_h

h

0–1000

intervention_time_h

h

0–100

restart_filament_g

g

0.1–10⁵

recovery_filament_g

g

0–10⁵

success_probability

fraction

0–1

  • Result: expected_recovery_time_h, expected_time_savings_h, expected_recovery_filament_g, expected_filament_savings_g, breakeven_probability_time.

  • Limitation: risk-neutral and assumes a single recovery attempt. The user supplies $p$.

4. early_stop_trend_alarm (new)

The tool fits a least-squares line $d(n) = a + bn$ to deviations measured during the print, such as warp lift, layer-shift offset or under-extrusion width, and extrapolates it to the final layer.

Alert

Condition

STOP

Latest deviation ≥ tolerance, or the projected final deviation ≥ tolerance

WATCH

Either value ≥ watch_fraction × tolerance

OK

Otherwise

Input

Unit

Range

layer_numbers

layers

list of 3–10,000 integers, strictly increasing, 0–100,000

deviations_mm

mm

list of the same length, each 0–50

tolerance_mm

mm

0.01–50

total_layers

layers

integer 1–100,000, ≥ last measured layer

watch_fraction

fraction

0.1–0.99 (default 0.5)

total_print_time_h

h

0.01–1000 (optional)

total_filament_g

g

0.1–10⁵ (optional)

Result:

  • alert_level

  • trend_slope_mm_per_layer, trend_r_squared

  • current_layer, current_deviation_mm

  • projected_final_deviation_mm, projected_exceedance_layer, layers_until_exceedance (the last two are null if the trend never reaches the tolerance)

  • remaining_fraction_of_print

  • time_saved_if_stopped_now_h, filament_saved_if_stopped_now_g (null if the optional inputs are omitted)

Limitations:

  • The trend is a straight-line extrapolation, so a low trend_r_squared means the projection is unreliable.

  • Savings assume time and filament are spread evenly across layers.

  • The deviations come from whatever is measuring the print (a camera or the user), and the tool does not check them.

5. layer_shift_strength_check (new)

A shift $s$ along the section width $W$ leaves a bonded overlap of $(W-s) \times D$. The load still acts through the centre of the upper part, so the shift adds an eccentric moment $Fs/2$.

$\sigma_{peak} = \dfrac{F}{A} + \dfrac{(M + Fs/2),c}{I}$, with $A = (W-s)D$, $I = D(W-s)^3/12$ and $c = (W-s)/2$.

Allowable stress = tensile_strength_MPa × interlayer_strength_factor. The result is compared against the same section with no shift.

Input

Unit

Range

section_width_mm (along the shift)

mm

1–500

section_depth_mm

mm

1–500

shift_mm

mm

0–500

axial_force_N (tension across layers)

N

0–10⁵

bending_moment_Nmm

N·mm

0–10⁸

tensile_strength_MPa (datasheet)

MPa

1–200

interlayer_strength_factor

fraction

0.05–1

required_safety_factor

–

1–20 (default 2)

At least one of the force and the moment must be positive. A shift of at least the full width returns safety_factor: 0 with a "separated" note rather than an error.

  • Result: bonded_area_mm2, area_retained_fraction, peak_stress_MPa, allowable_stress_MPa, safety_factor, intact_safety_factor, strength_retained_fraction, meets_requirement, note.

  • Limitations:

    • Uses beam theory on a solid rectangle. It ignores infill and perimeters, stress concentration at the step, and fatigue.

    • The interlayer factor is a user assumption and should be measured.

Demo record

  • demo/inspector_transcript.md: MCP Inspector (CLI mode) calls with full responses:

    • the tool list with schemas;

    • two HW4 tools;

    • both new tools;

    • three invalid inputs, covering a schema range, a domain rule and a new tool.

  • demo/claude_code_transcript.md: Claude Code calling the tools from plain-language questions, including a unit conversion (480 min → 8 h).

Client / server boundary

Server (this repo):

  • the equations;

  • unit and range validation, and the input schemas that publish it;

  • typed structured results;

  • error messages.

It is deterministic and stateless, makes no network calls, and cannot send commands to a printer.

Client (Claude Code, Claude Desktop, Inspector):

  • understanding the request;

  • converting units (minutes → hours, percent → fraction, diameter → radius);

  • choosing the tool;

  • asking for missing inputs instead of inventing them;

  • explaining the result.

Human: makes the decision. The server can report STOP, but it never stops a print.

Requirement

Interview evidence

Tool

R1: Detect failures early

Unattended overnight prints; adhesion and warping failures that spaghetti detection misses; wanting to pause prints in advance

early_stop_trend_alarm

R2: Judge function, not appearance

Visually imperfect parts are acceptable if they work; a part that looks fine may still be structurally weak

layer_shift_strength_check, check_functional_geometry

R3: Evidence and approval before changes

Distrust of automatic correction

All tools are read-only and return intermediate values

R5: Run offline

Concern about proprietary designs in the cloud

Local stdio server, no network

What a human should verify before acting

  • All tools: check that the arguments the client sent match the real part and printer. Units are the most likely source of error.

  • early_stop_trend_alarm:

    • look at the print before cancelling;

    • the trend is a straight-line extrapolation, and a low trend_r_squared means it is unreliable;

    • the input measurements are not verified by the tool.

  • layer_shift_strength_check:

    • use measured strength values;

    • halving interlayer_strength_factor from 0.5 to 0.25 drops the demo safety factor from 4.57 to about 2.3;

    • the model ignores infill, stress concentration at the step and fatigue;

    • for load-critical parts, pull-test a coupon with the same shift.

  • check_recovery_feasibility / expected_recovery_savings: the per-layer correction limit and the success probability are assumptions that should be measured.

Repository layout

tools.py       pure-Python tool functions (HW4 tools verbatim + 2 new); no MCP dependency
server.py      MCP server: schemas, result models, annotations, error mapping
tests/         pytest: hand-checked values, edge cases, invalid inputs, in-process MCP calls
demo/          Inspector CLI script + transcript, Claude Code transcript
LICENSE        MIT

AI usage

Claude Code (Claude Opus 5.5) helped implement and test this server. The tool equations, ranges and design decisions were reviewed by the author.

Related MCP Connectors

Related MCP Servers

  • F
    license
    A
    quality
    D
    maintenance
    An intelligent 3D printing assistant that enables users to analyze meshes, generate optimal print profiles, and automate PrusaSlicer operations through an MCP client. It provides a comprehensive suite of tools for geometric analysis, printability checks, filament recommendations, and post-print diagnostics.
    17
    10
    -
  • A
    license
    A
    quality
    C
    maintenance
    MCP server for real FDM 3D-printing slicing, quoting, and design-for-manufacturability analysis via the FabTally API, supporting 12 printer profiles and 12 materials. Includes free discovery/printability tools and paid slice/quote/orientation tools settled via x402 (USDC on Base).
    6
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    MCP server for pre-print QA of Bambu Studio projects, providing tools to inspect models and 3MF files, validate risky settings, create support variants, and open files in Bambu Studio.
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Experimental load-path analysis for 3D-printed STL parts, with stress and movement comparisons across CAD revisions, PNG captures, visual reviews, and persistent human-guided design sessions. Runs locally through a stdio MCP server.
    MIT