bottle-cap-mcp
MCP server for bottle-cap CAD workflow, providing tools for generating precise caps, filling holes, repairing meshes, and generating visual meshes via CadQuery, PyMeshLab, and the Meshy API.
README
bottle-cap-mcp
NitroStack MCP server exposing three tools for the bottle-cap-cad workflow.
Vision/dimension extraction from the source photo happens client-side
(in Claude, the MCP client) — none of these tools re-derive dimensions from
pixels; generate_visual_mesh is the one exception, since Meshy infers
geometry directly from the image itself.
Tools
| Tool | Input | Backend | Network |
|---|---|---|---|
generate_precise_cap |
dimensions JSON | CadQuery (Python — local subprocess, or remote via CAD_API_URL) |
none / HTTPS |
fill |
hole/cavity geometry JSON (circle/rectangle/polygon, uniform or tapered) | CadQuery (Python — local subprocess, or remote via CAD_API_URL) |
none / HTTPS |
repair_mesh |
mesh URL or base64 | PyMeshLab (Python — local subprocess, or remote via CAD_API_URL) |
none / HTTPS |
generate_visual_mesh |
raw image (base64) | Meshy API | HTTPS |
Setup
npm install
pip install -r requirements.txt --break-system-packages # or your own venv
cp .env.example .env # set MESHY_API_KEY
npm run build
npm start
For local iteration without a build step: npm run dev.
Deploying to NitroCloud (or any Node-only host)
NitroCloud's managed hosting runs this server in a Node-only container —
there's no python3 there for getPythonCommand() to find, so
fill/generate_precise_cap/repair_mesh fail with "Could not find a
working Python interpreter" if deployed as-is.
The fix: run api/server.py (a small FastAPI wrapper around the same three
CAD scripts) somewhere that does have Python — your own machine, a VPS,
Render, Railway, Fly.io, etc. — and point the NitroCloud deployment at it.
1. Run the API somewhere with Python:
# locally, for testing (tunnel with ngrok/cloudflared if NitroCloud needs to reach it)
pip install -r requirements.txt --break-system-packages
export CAD_API_KEY=<pick-a-secret>
uvicorn api.server:app --host 0.0.0.0 --port 8787
# or as a container, anywhere that runs Docker:
docker build -f api/Dockerfile -t bottle-cap-cad-api .
docker run -d -p 8787:8787 -e CAD_API_KEY=<pick-a-secret> bottle-cap-cad-api
pymeshlab's mesh I/O plugins are Qt-based and needlibgl1/libglu1-mesapresent on the host even for fully headless use — the Dockerfile already includes them, but a bare VPS/Render/Railway box may need them installed separately (apt-get install libgl1 libglu1-mesa), or/repaircalls will fail withUnknown format for load: stl.
2. Point the NitroCloud deployment at it — set these in NitroCloud's
environment variables dashboard (not just your local .env, since that
doesn't travel with the deploy):
CAD_API_URL=https://<wherever-you-ran-the-api-above>
CAD_API_KEY=<same secret as above>
That's it — fill.tools.ts/cap.tools.ts/repair.tools.ts check for
CAD_API_URL at call time and switch to HTTP automatically. Leave it unset
for local NitroStudio dev and they fall back to the original local-subprocess
behavior, unchanged.
Structure
bottle-cap-mcp/
├── src/
│ ├── app.module.ts # registers the tool providers
│ ├── main.ts # bootstrap / entrypoint
│ └── tools/
│ ├── shapes.ts # shared circle/rectangle/polygon zod schema
│ ├── cap.tools.ts # generate_precise_cap
│ ├── fill.tools.ts # fill
│ ├── repair.tools.ts # repair_mesh
│ ├── mesh.tools.ts # generate_visual_mesh (pure TS, calls Meshy)
│ ├── python-runtime.ts # local python3/python/py auto-detection
│ └── cad-api-client.ts # optional HTTP client for api/server.py (CAD_API_URL)
├── cad/
│ ├── precise_cap.py # CadQuery threaded-cap builder
│ ├── fill.py # CadQuery plug builder
│ └── repair_mesh.py # PyMeshLab repair pipeline
├── api/
│ ├── server.py # FastAPI wrapper exposing /fill /cap /repair over HTTP
│ └── Dockerfile # standalone image for hosting api/server.py
├── package.json
├── tsconfig.json
└── requirements.txt
Known gaps (carried over from the design discussion)
Real threads— resolved:precise_cap.pynow builds a solid, closed top and cuts a blind bore (not a through-hole), and unions one or more real helical thread ridges onto the skirt's inner wall via a triangular/trapezoidal profile swept along acq.Wire.makeHelix()path (seemake_thread_solid).threadStarts(1-4),threadDepth, andtopThicknessare new optional fields ongenerate_precise_cap—threadPitchstill falls back to an approximate PCO 1810-style pitch (3.18mm, single start) when omitted. This is a parametric approximation tuned for FDM printing, not a certified thread-spec generator; swap incq_warehouse's generators if you need an exact standard spec (e.g. a certified PCO 1881 mating thread).- Polygon flush caps:
fill'scapStyle: "flush"is implemented for circle/rectangle top shapes only. A polygon top withflushis downgraded tononebyfill.tools.ts(with a warning returned to the caller) rather than silently failing. - Loft corner fillets: for tapered holes, rectangle corner radii are applied at the wire level before lofting (an approximation), since filleting a lofted solid's edges directly is more involved than filleting a simple extrusion's vertical edges.
NitroCloud deployment target— resolved: NitroCloud's managed hosting is Node-only (no Python interpreter available for theexecFilecalls). CadQuery/PyMeshLab now run behind a separateapi/server.pymicroservice, called over HTTP whenCAD_API_URLis set — see "Deploying to NitroCloud" above. Local NitroStudio dev is unaffected (falls back to the original subprocess path whenCAD_API_URLis unset).main.tsbootstrap call:NitroFactory.createMcpServer(...).listen()follows NitroStack's documented NestJS-style pattern, but the exact factory method wasn't pinned down in the source discussion — confirm against your installed NitroStack version.- Meshy polling:
mesh.tools.tspolls for task completion; swap for Meshy's webhook callback in production to avoid long-held connections.
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
E2B
Using MCP to run code via e2b.
Neon Database
MCP server for interacting with Neon Management API and databases
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.