[{"element_type":"alert","content":"\u003cp\u003eNever leave a CNC machine, or AI controlled device unattended. That is an unnecessary risk to life and limb, and the safety of yourself + others + property is paramount at all times. -- There are usually laws about safety in every country, and all the more so for machines moving by themselves around humans! -- -- -- -- -- -- -- -- --\u003c/p\u003e\n\n\u003cp\u003e\u003cstrong\u003e\u003cem\u003eDo Not Attempt to recreate this project,\u003c/em\u003e\u003c/strong\u003e it is the documentation of an experiment by a capable professional who maintained safety and presence at the machines emergency stop (power switch) at all times of operation.\u003c/p\u003e\n","metadata":{"markdown":"Never leave a CNC machine, or AI controlled device unattended. That is an unnecessary risk to life and limb, and the safety of yourself + others + property is paramount at all times. -- There are usually laws about safety in every country, and all the more so for machines moving by themselves around humans! -- -- -- -- -- -- -- -- --\n\n\n__*Do Not Attempt to recreate this project,*__ it is the documentation of an experiment by a capable professional who maintained safety and presence at the machines emergency stop (power switch) at all times of operation.","alert_type":"danger","icon":"exclamation"}},{"element_type":"text","content":"\n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n        \u003cp\u003e\u003cem\u003eVia the powers of\u003c/em\u003e \u003cstrong\u003e\u003cem\u003eCircuitPython\u003c/em\u003e\u003c/strong\u003e, and Adafruit WipperSnapper, I have gifted my CNC a new set of features...\u003c/p\u003e\n\u003cp\u003eV1 avoids altering the CNC firmware or machine at all, because that would be less accessible (or reversible)!\u003c/p\u003e\n\u003cp\u003eIt supports the existing software control system (wifi) by adding an MCP server with\u003cstrong\u003e safety\u003c/strong\u003e \u003cspan style=\"text-decoration: underline;\"\u003ebaked-in\u003c/span\u003e\u003cstrong\u003e \u003c/strong\u003e(motion rules + human approvals) along with skills for CNC probing, tool setting, roughing and visual feedback. Utilises a directly attached or MQTT based feedback system for the tool-setter and probe.\u003c/p\u003e\n      \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n","metadata":{}},{"element_type":"user_image","content":"https://cdn-learn.adafruit.com/user_assets/assets/000/002/586/original/Screenshot_2026-09-07_161159.png?1788794079","metadata":{}},{"element_type":"text","content":"\n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n        \u003ch3\u003eWhat hardware you ask?\u003c/h3\u003e\n      \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n","metadata":{}},{"element_type":"text","content":"\n  \n  \n  \n  \n  \n  \n        \u003cul\u003e\n\u003cli\u003eAn old \u003ca href=\"https://www.snapmaker.com/snapmaker-2\" target=\"_blank\"\u003eSnapmaker 2.0 A350\u003c/a\u003e 3-in-1 3D printer / CNC / Laser (with Rotary extension), which relies on a touchscreen android device (handles the WiFi API etc) driving an STM32 compatible machine controller running a marlin fork. Utilises their Luban software for sending whole Jobs or single commands.\u003c/li\u003e\n\u003c/ul\u003e\n      \n\n\n\n\n\n","metadata":{}},{"element_type":"user_image","content":"https://cdn-learn.adafruit.com/user_assets/assets/000/002/582/original/Screenshot_2026-09-07_145733.png?1788789470","metadata":{}},{"element_type":"text","content":"\n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n        \u003cul\u003e\n\u003cli\u003eA cheap-as-chips tool-setter, with optional blowing post (unintegrated currently as needs an Air Line).\u003cbr\u003e(Looks an orangey gold in the image above, with the large central silver circular testing pad)\u003cbr\u003e\u0026nbsp;\u003c/li\u003e\n\u003cli\u003eStandard $50 touch probe tool, mines the one with \"USB-C\" connector for non-usb things.\u003c/li\u003e\n\u003c/ul\u003e\n      \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n","metadata":{}},{"element_type":"user_image","content":"https://cdn-learn.adafruit.com/user_assets/assets/000/002/583/original/Screenshot_2026-09-07_150609.png?1788790050","metadata":{}},{"element_type":"text","content":"\n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n        \u003cp\u003eFor the Touch Sensor events to be received by the MCP server, use WiFi, or GPIO, or a USB-GPIO device:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eA microcontroller or Single Board Computer compatible with Adafruit Blinka, for CircuitPython support on the PC / SBC. I used an\u0026nbsp;\u003ca href=\"https://www.adafruit.com/product/5302\"\u003eAdafruit KB2040\u003c/a\u003e (same chip as Pico) running U2-IF, connected to the laptop.\u003cbr\u003e\u0026nbsp; \u0026nbsp;\u003cspan style=\"text-decoration: underline;\"\u003e\u003cem\u003eOr\u003c/em\u003e\u003c/span\u003e\n\u003c/li\u003e\n\u003cli\u003eA Network-Enabled device capable of sending the touch sensor events to an MQTT topic, like a WiFi enabled board supported by \u003ca href=\"https://io.adafruit.com/works-with-wippersnapper\"\u003eAdafruit WipperSnapper\u003c/a\u003e. I used the \u003ca href=\"https://www.adafruit.com/product/4985\"\u003eAdafruit FunHouse\u003c/a\u003e for my prototype.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eThe MCP \u003ca href=\"https://github.com/tyeth/Luban/blob/startup/base/src/server/services/mcp/README.md\" target=\"_blank\"\u003eReadme\u003c/a\u003e contains further instructions for how to setup Blinka and the python virtual environment, or the MQTT option, although hopefully the Preferences -\u0026gt; MCP page should be mostly self explanatory.\u003c/p\u003e\n      \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n","metadata":{}},{"element_type":"guide","content":"https://learn.adafruit.com/circuitpython-libraries-on-any-computer-with-raspberry-pi-pico/running-circuitpython-code-without-circuitpython","metadata":{"guide_id":"3317","page_id":"26922"}},{"element_type":"text","content":"\n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n        \u003ch5\u003eYour GPIO to USB or WiFi thing should end up looking a bit like this:\u003c/h5\u003e\n      \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n","metadata":{}},{"element_type":"user_image","content":"https://cdn-learn.adafruit.com/user_assets/assets/000/002/584/original/Screenshot_2026-09-07_151616.png?1788814568","metadata":{}},{"element_type":"text","content":"\n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n        \u003cp\u003eOr this:\u003c/p\u003e\n      \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n","metadata":{}},{"element_type":"user_image","content":"https://cdn-learn.adafruit.com/user_assets/assets/000/002/585/original/Screenshot_2026-09-07_152000.png?1788814505","metadata":{}},{"element_type":"text","content":"\n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n        \u003ch3\u003eCode related vibes, and my usual sprinkling of Health \u0026amp; Safety paranoia:\u003c/h3\u003e\n      \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n","metadata":{}},{"element_type":"text","content":"\n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n        \u003cp\u003eI started small, with the tool height detector (tool-setter?) as it has a relatively large safety margin for error if you plunge down too far. An initial move to the area at top gantry height, then gentle descending march.\u003c/p\u003e\n\u003cp\u003eAfter getting that running along with some initial safety \"laws of motion\", the probe tool was next. This quickly led to overconfidence, soon paid for in a later accident during which it didn't raise Z to top position before a large horizontal move (stock and probe tip danced - wood won - old tip now has a slight kink).\u003c/p\u003e\n      \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n","metadata":{}},{"element_type":"text","content":"\n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n        \u003cp\u003eShort video of the setup \u003cstrong\u003e\u003ca href=\"https://youtube.com/shorts/vX3a7dSMnNY\" target=\"_blank\"\u003e\u003cspan style=\"text-decoration: underline;\"\u003ehere\u003c/span\u003e\u003c/a\u003e \u003c/strong\u003e(age restricted to avoid people who don't RTFM from injuring themselves)\u003c/p\u003e\n      \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n","metadata":{}},{"element_type":"user_image","content":"https://cdn-learn.adafruit.com/user_assets/assets/000/002/589/original/Screenshot_2026-09-07_190150.png?1788804369","metadata":{}},{"element_type":"text","content":"\n        \u003cp\u003eAfter about 50-odd PRs, and a reasonable last test: calculating the true center-point after safely probing a workpiece remotely from the park last night, beer in hand...(\u003cem\u003e\u003cstrong\u003eDo\u0026nbsp;\u003cspan style=\"text-decoration: underline;\"\u003eNot\u003c/span\u003e do what I do)...\u003c/strong\u003e\u003c/em\u003eI can confidently say the safety rules codified in the solution are pretty good, stopping an agent from mistakes a few times that day.\u0026nbsp;\u003c/p\u003e\n\u003cp\u003e\u003cspan style=\"text-decoration: underline;\"\u003e\u003cem\u003e\u003cstrong\u003eNever\u003c/strong\u003e\u003c/em\u003e\u003c/span\u003e\u003cem\u003e\u003cstrong\u003e leave a running or connected machine unattended!\u003c/strong\u003e\u003c/em\u003e\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://github.com/tyeth/Luban/releases/latest\" target=\"_blank\"\u003ehttps://github.com/tyeth/Luban/releases/latest/ (v4.15.2-mcp-alpha.8)\u003c/a\u003e\u003cbr\u003e[Mac Users need to unblock it first or re-sign it with a local certificate to avoid warnings]\u003c/p\u003e\n\u003ch3\u003eSafety First!\u003c/h3\u003e\n\u003cp\u003eMy aim was to ensure the Skills offered to agents allowed easy use of the api, and safety guidance (along with machine params expected motion rules etc).\u003c/p\u003e\n\u003cp\u003eHowever anyone using AI knows they love to ignore advice and required steps from Skills and sessions, meaning an MCP server should codify any safety rules required, otherwise Agents will attempt to find a shortcut or ignore rules.\u003c/p\u003e\n\u003cp\u003eTo that end, I felt it necessary to not allow the MCP server to connect to the CNC machine (use the Connect button / API in Luban software).\u003cbr\u003eHuman intervention / sign-off is therefore required to enable agentic / remote use.\u003c/p\u003e\n\u003cp\u003eOn top of that I added a second gate / verification factor, that a webpage must be opened by a human (local machine / network* only) to verify the intended GCode moves and then approve the job and feed back a 2FA code to the Agent.\u003c/p\u003e\n\u003cp\u003e\u0026nbsp;To speed life up I've allowed the agent to poll for approval instead of pasting the code, and I've experimented with asking an agent to approve jobs for me which I've rules around - it allowed the one approval but not for future jobs/moves, each requiring explicit consent+approval.\u003c/p\u003e\n      ","metadata":{}},{"element_type":"user_image","content":"https://cdn-learn.adafruit.com/user_assets/assets/000/002/587/original/Screenshot_2026-09-07_184207.png?1788804440","metadata":{}},{"element_type":"text","content":"\n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n        \u003ch3\u003eTesting with low intelligence/effort models\u003c/h3\u003e\n\u003cp\u003eI started with a Sonnet model using the skills and MCP server, pretty effective, although at times I used Opus or Fable for new untested mcp tool calls. \u003cem\u003eOnly \u003c/em\u003eone probe tip was harmed during the making of this software!\u003c/p\u003e\n\u003cp\u003eMost recently for the surface mapping and center finding probing operations I've been trying GPT5.6-Sol on \u003cem\u003eLight thinking\u003c/em\u003e, which has still been very effective, only once misremembering a preferred coordinate from the start of a very long conversation.\u003c/p\u003e\n\u003ch3\u003eRemote MCP Access\u003c/h3\u003e\n\u003cp\u003eI particularly appreciated how the OpenAI tunnel-client worked \u003cem\u003e(don't forget Developer Mode in user settings)\u003c/em\u003e, running locally to forward the MCP, and then once setup then the Web sessions could access my mcp server too. ChatGPT also allowed easily updating the skills installed by just asking for the latest PR copy to be utilised.\u003c/p\u003e\n\u003cp\u003eMCP Oauth - Having originally used the Luban MCP on my host laptop, and not wanting to reload the MCP server after each change, I was going via a script and the loopback (127.0.0.1) network interface which works fine.\u0026nbsp; Alas, once I'd shifted the MCP to another machine life became more complex for Claude (wanting loopback only - fixed with `ssh -L 40889:127.0.0.1:40889 pi@192.168.1.153`, then wanting OAuth). I added a minimal registration pathway to the MCP server so now we ignore it and claude shuts up.\u003c/p\u003e\n      \n\n\n\n\n\n\n\n\n\n\n\n\n","metadata":{}},{"element_type":"text","content":"\n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n        \u003ch2\u003eMCP Server Tooling Details:\u003c/h2\u003e\n      \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n","metadata":{}},{"element_type":"faq","content":" Toggle Collapsible list of MCP tool names and descriptions \n","metadata":{"markdown":"Toggle Collapsible list of MCP tool names and descriptions","color":"black","icon":"question-mark","expanded":"false"}},{"element_type":"text","content":"\n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n        \u003ch2\u003eWhat's next?\u003c/h2\u003e\n\u003ch3\u003eDigital Read Out (D.R.O.) showing the current X/Y/Z Coordinates\u003c/h3\u003e\n\u003cp\u003eHaving a circuitpython code capable device it occurred to me that I could add a Digital Read Out (x/y/z) to my machine relatively easily, getting the MCP server to push latest numbers to an I2C display like this one:\u003c/p\u003e\n      \n\n\n\n\n\n\n\n\n\n\n\n","metadata":{}},{"element_type":"product","content":"https://www.adafruit.com/product/879","metadata":{"quantity":"1","description":"","name":"","url":"","featured":"true"}},{"element_type":"text","content":"\n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n        \u003ch3\u003eInspection jobs from FreeCAD / Fusion / CAM software\u003c/h3\u003e\n\u003cp\u003eI've got the first newly written post-processor for Fusion going, and it's successfully generated a probing job, verified as compatible with the MCP, so by the end of this week we should be sat up at the big boys table...\u003c/p\u003e\n      \n\n\n\n\n\n\n\n\n\n\n","metadata":{}},{"element_type":"user_image","content":"https://cdn-learn.adafruit.com/user_assets/assets/000/002/588/original/Screenshot_2026-09-07_184645.png?1788803221","metadata":{}}]