Skip to content

Add a headless MCP server for agent-driven texturing#99

Open
urib94 wants to merge 1 commit into
CNCKitchen:mainfrom
urib94:feat/mcp-server
Open

Add a headless MCP server for agent-driven texturing#99
urib94 wants to merge 1 commit into
CNCKitchen:mainfrom
urib94:feat/mcp-server

Conversation

@urib94

@urib94 urib94 commented Jul 13, 2026

Copy link
Copy Markdown

Add a headless MCP server for agent-driven texturing

What this is

A self-contained Model Context Protocol (MCP) server (mcp/) that exposes BumpMesh's
mesh-processing pipeline to AI agents and automation. It lets a tool/agent apply displacement
textures to a model programmatically — STL/OBJ/3MF in, displaced STL/3MF out — with no browser,
no GPU, and no data upload
(same privacy guarantee as the web app).

Motivating use case: 3D-print prep. An assistant can grip-texture a handle, knurl a knob, or add
carbon-fiber to a panel as one step in a larger "design → texture → slice" workflow, driven from
natural language.

Why it's low-risk to the existing app

The whole thing reuses js/*.js directly — it does not reimplement any geometry code, so it
can't drift from the app. The export pipeline (exportPipeline.js) already depends only on
three (as math), meshIndex.js, and fflate; WebGL is confined to the viewer/preview, which
the server never touches.

Two pure, behavior-preserving refactors make the pipeline callable headlessly:

  • js/exporter.js — extract buildSTLBytes(geometry) / build3MFBytes(geometry) (return
    Uint8Array). exportSTL / export3MF keep their signatures and the exact browser download
    path; output bytes are identical.
  • js/stlLoader.js — extract parseModelBuffer(arrayBuffer, ext) (parse + cleanup + bounds).
    The File-based loaders (loadModelFile, loadSTLFile, …) keep their signatures and wrap it
    after FileReader.

No changes to viewer.js / previewMaterial.js or any UI behavior.

Tools

Tool Purpose
bumpmesh_list_textures The 24 built-in presets (name, category, description).
bumpmesh_inspect_mesh Triangle count, bounding box, surface area, watertightness, shells.
bumpmesh_texturize Full pipeline: model + texture (preset or custom image) + projection/UV/amplitude/masking/decimation → writes STL/3MF, returns a summary.
bumpmesh_subdivide Adaptive subdivision only.
bumpmesh_decimate QEM decimation to a target triangle count.
bumpmesh_validate_mesh Open edges, non-manifold edges, shells, slivers.
bumpmesh_place_on_bed Orient a chosen/auto face down onto Z = 0.

Plain-JS ESM, no build step, stdio transport, zod-validated strict inputs (unknown
params error), actionable error messages, stdout kept protocol-clean.

Build / install change

Adds a minimal npm-workspaces root package.json declaring three + fflate, so the shared
js/ modules resolve their dependencies from a single npm install at the repo root — this
also makes the existing bench-*.mjs / diag-*.mjs scripts reproducible. The previously untracked
manifests are now tracked (node_modules/ stays ignored). .3mf input works under Node via a
small @xmldom/xmldom DOMParser shim installed by the server before any js/ module loads
(js/ itself is untouched).

Testing

node:test suite, 26 tests, no GPU, runnable via npm test --workspace mcp:
round-trip texturize (STL byte-length invariant, re-parse, watertight output), STL/OBJ/3MF
read + round-trip, subdivide/decimate/place-on-bed, list_textures, strict-validation and
unknown-texture error paths.

Try it

npm install                 # at the repo root (workspaces)
node mcp/server.mjs         # stdio MCP server

Client config (Claude Desktop / Code):

{ "mcpServers": { "bumpmesh": { "command": "node", "args": ["/absolute/path/to/stlTexturizer/mcp/server.mjs"] } } }

See mcp/README.md for the full tool reference and parameters.

Adds a self-contained `mcp/` Model Context Protocol server that exposes
BumpMesh's mesh-processing pipeline to AI agents (STL/OBJ/3MF in, displaced
STL/3MF out) with no browser, GPU, or data upload. It imports the existing
`js/*.js` modules directly, so it never drifts from the app's geometry code.

Tools (bumpmesh_*): list_textures, inspect_mesh, texturize, subdivide,
decimate, validate_mesh, place_on_bed. Plain-JS ESM, stdio transport, no
build step; zod-validated strict inputs; node:test suite (26 tests).

Two pure, behavior-preserving refactors let the pipeline run headlessly:
- exporter.js: extract buildSTLBytes/build3MFBytes; exportSTL/export3MF keep
  their signatures and browser download path.
- stlLoader.js: extract parseModelBuffer; File-based loaders unchanged.

Build config: add an npm-workspaces root package.json (three, fflate) so the
shared js/ modules resolve their deps from one root install; stop gitignoring
the tracked manifests. 3MF input works in Node via an xmldom DOMParser shim
(js/ untouched).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant