DEV Community

MCP servers, and what they let a local model actually do: Blender, CADCraft and the DWG problem

The protocol, briefly, so the rest can be concrete

Two years ago this month Anthropic open-sourced the Model Context Protocol (25 November 2024).

In December 2025 it was donated to the Agentic AI Foundation, a directed fund under the Linux Foundation co-founded by Anthropic, Block and OpenAI with support from Google, Microsoft, AWS, Cloudflare and Bloomberg - so today it is a shared standard rather than one vendor's plugin system.

Its current specification revision is dated 2026-07-28, and that revision does something most explainer posts miss: it makes the protocol stateless. The initialize handshake is gone, sessions and the Mcp-Session-Id header are removed from Streamable HTTP, every request carries its own protocol version and client capabilities in _meta, and servers must implement a server/discover RPC to advertise versions and identity.

Roots, Sampling and Logging were deprecated outright, with a twelve-month removal window. In other words: the protocol is being stripped of statefulness, and of the features that used to make a server "smart", in favour of one primitive that matters more - tools.

That is the argument I want to make here, because it is exactly the thing our kind of setup is for. When you run inference on your own box, the model is not short of knowledge so much as short of reach. It can write a Python script; it cannot, by itself, open your file, run your software, look at the result and correct itself.

MCP servers are the layer that supplies that reach without any tuning, no retraining and no cloud account - which is why they fit an article series about engines like llama.cpp, Strata, Avalon and Xolotl better than most people expect.

Three things I looked at in practice: the Blender bridge (a 2D drawing in, a 3D render out), CADCraft and its batch/DWG tooling, and ArtCraft's deliberate CLI-and-MCP-first design. And one thing I use every day: this blog's own publishing pipeline is an MCP server with 138 tools, and none of it is run by a model - which is the honest caveat the rest of this piece has to carry.

MCP is a JSON-RPC 2.0 conversation with a small number of agreed verbs. A server offers three things:

  • tools (functions the model may call)
  • resources (addressable content, e.g. cadcraft://drawing)
  • prompts (named templates)

The client side used to offer more than it does now: Sampling, Roots and Logging were deprecated in the 2026-07-28 revision with a twelve-month removal window under a new feature-lifecycle policy, and the recommended migration for each is "stop using the protocol for it" - pass directories as tool arguments, call your provider API directly, log to stderr.

Reading that changelog as a user, not an implementer, the direction of travel is obvious: the protocol wants to be a plumbing standard, not a model runtime.

Two transports are in the spec: stdio (the spec says clients should prefer it where possible - your process launches the server itself) and Streamable HTTP, with the older HTTP+SSE transport now formally deprecated since 2025-03-26.

Everything above that matters for us is in the boring parts of the 2026-07-28 changelog: it removed the initialize handshake and made every request carry its own protocol version and client capabilities in _meta, so there is no session to break - a local tool call is one request, and if the connection drops you re-issue it; servers must implement server/discover to advertise their versions and identity, instead of clients guessing; tools/list results now carry ttlMs and cacheScope, and servers should return tools in a deterministic order so client-side caching and prompt-cache hit rates survive.

Read that again as someone running a small-context model on 24 GB of VRAM: the spec is explicitly trying to keep tool listings from eating your context window.

That last point is why this series has an interest in MCP at all. On a constrained machine, every extra tool schema in the prompt is a token tax you pay on each turn; the protocol now tries to make that tax cacheable and predictable. Which is the same trade-off we keep writing about in a different currency for engines like llama.cpp - the budget is finite, spend it deliberately.

Blender MCP: a drawing in, a render out

First, naming, because it wastes hours when you get it wrong. The project most people search for as "Blender MCP" is ahujasid/blender-mcp, which was renamed on 16 September 2026 to mcp-for-blender ("Community plugin to control Blender 3D with any LLM of your choice. Not affiliated with the official Blender Foundation").

MIT licence, ~34k stars. The PyPI package is now mcp-for-blender - latest 2.2.7, uploaded 4 November 2026 - and blender-mcp is kept as a compatibility wrapper so uvx blender-mcp still works. There are no GitHub releases at all: versioning happens on PyPI only, which is worth knowing when you want to pin it.

And do not confuse it with the Blender Foundation's own Labs MCP server, which is a separate project aimed at scene analysis and carries its own security warning.

The bridge is two pieces, and the direction of the connection is the part people get backwards: an addon (addon.py, installed as blender_mcp.py; its bl_info says version (1,8), minimum Blender 3.0.0) that runs inside Blender and hosts a TCP socket server on localhost:9876 (BLENDER_HOST / BLENDER_PORT or --port override it, and remote connections need "Bind Address" + "Allow Remote Connections" in the addon preferences); an MCP server (src/blender_mcp/server.py, launched by your client over stdio with uvx mcp-for-blender) which is a TCP client of that socket.

So the model talks to a process you started, which dials into Blender. Commands are JSON over TCP ({"type", "params"} in, {"status", "result|message"} out) with an addon protocol-version handshake (15 today).

Nine documented tools: execute_blender_code (arbitrary Python, executed with exec() inside Blender's process), look (viewport, camera and named angles; can also show a render or an image file), get_scene_info, generate_3d, search_assets / import_asset, get_addon_status, and two telemetry controls.

Below that there is a constrained command set (get_object_info, list_scene_items, get_viewport_screenshot, pick_viewport_object, describe_node_type, bpy_api_lookup, export_scene) and, on top of it, unrestricted bpy scripting - which is why the project says plainly that the model "writes Blender Python itself" for modelling, layout, materials, animation, rigging and retopology.

The actual 2D-in / 3D-out path

This is where most write-ups get sloppy, so here is the precise split, from the README and the source rather than from vibes. In this project, generate_3d takes an image as its sole input - "an absolute image file path or an http(s) URL" - and hands it to an external generation service (Meshy, Tripo, Hyper3D Rodin or Hunyuan3D), returning a textured .glb that is then imported into the scene.

Caveats straight from the tool description: images attached in chat cannot be passed, you must supply a path or URL; one object per call; Hyper3D wants a folder of up to five views of one object; paid services need credits or your own API key; and the request waits at most 45 seconds before handing back a job handle.

So "a drawing becomes a 3D render" is real, but the geometry comes from an API, not from your machine.

The documented alternative path - the one in their demo video - is reference-driven scene building: the model reads the image visually and then writes bpy code to lay out objects that match it. That is vision plus code, not geometry extraction. And look(image=...) only displays an existing image or render back into the conversation; it does not put it in the scene.

Not in this project, verified by absence: there is no Grease Pencil support anywhere in the repo (zero matches for "grease" across the addon, the server and the docs), no trace-curve/image-to-curve conversion, and no built-in "add image as a reference plane" command. Those things are only reachable by writing the Python yourself through execute_blender_code.

If you want the same job done without an API call, that belongs to other software: FishWoWater/trellis_blender runs TRELLIS/TRELLIS.2 inside Blender for text- and image-to-3D, on your own hardware; gd3kr/BlenderGPT (MIT, 2023-era, last touched June 2024) has an LLM writing bpy scripts without MCP; and blendergpt.org is a separate commercial assistant whose "Blender Sync" pushes GLB files in.

Saying which one does what is the whole point: an MCP server does not add modelling capability, it adds a path into a modeller that already has it.

What it costs to run this Blender must be running with a GUI and the addon enabled (N panel → Start MCP Server); viewport capture needs a real 3D viewport area, and nothing in the docs claims headless support.

The socket has no authentication or encryption - anyone who can reach that port can execute Python in your Blender session - so keep it on localhost or tunnel it over SSH, and heed the README's warning: "ALWAYS save your work before using it."

An optional BLENDER_MCP_SAFE_MODE=1 validates the code with an AST allowlist, and its own source says it is not a sandbox. Asset downloads happen inside Blender's main thread, so the UI freezes while they fetch; the docs note that file size roughly quadruples per resolution step, "so ask for 1k or 2k". look caps images at 768 px by default, and the reason given in the code is the one I keep coming back to: images stay in the conversation, and conversations cost context.

CADCraft: the boring, useful half - batch jobs and DWG files

CADCraft (storytold/cadcraft) is an AutoCAD-style drafting application written in Rust from scratch - its own geometry core, no FreeCAD or OpenCascade in sight - licensed MIT OR Apache-2.0, latest release v0.19.0 (9 November 2026).

It has no PyPI, npm or crates.io package: you build it from source with cargo run --release -p cadcraft or download signed installers for Windows, macOS, Linux, FreeBSD and riscv64, plus a WebAssembly build that runs in a browser.

What matters here is that it ships three faces of the same binary, and one of them is deliberately the one meant for machines:

cadcraft-cli info drawing.dxf
cadcraft-cli convert drawing.dwg detail.png --window 0,0,20000,15000
cadcraft-cli run --sample --script 'CIRCLE 22,3 1' --save out.dxf --export out.png

Those are quoted from its own docs. info, convert, run, commands and mcp are the subcommands; output is JSON on stdout (JSON-lines for run), errors go to stderr, exit codes are 0/1/2 - it follows the project's numbered CLI conventions (RFC-0012) so a shell script can depend on it.

This is what "automate a simple task" looks like when it is done properly: convert a DWG to a PNG detail crop, run a saved .scr script over a folder of drawings, get machine-readable results back, and no GUI anywhere.

Then the same binary speaks MCP:

cadcraft-cli mcp # headless stdio server, in-process session, no window
cadcraft --control 7979 & # or bridge to the running app
cadcraft-cli mcp --connect 127.0.0.1:7979

Its documented tool surface is command_line, script, execute {command, params}, list_commands, inspect_drawing, query_entities, plus subcommands that do real analysis - shapes (perimeter/area/centroid of closed loops), usage (a layer/block/style cross-reference for a PURGE preview), loops (implied closed loops from loose LINE/ARC chains) - and render, which returns a PNG so the caller can see what it did.

There are resources too: cadcraft://drawing and cadcraft://commands. The README's own sentence for this is better than my paraphrase: "Every menu item, tool and prompt is a command. Agents can type at the command line exactly like a person, call any command with JSON, inspect the drawing to verify their work, and render it - over MCP, a JSON control channel, or the CLI."

The session it documents is instructive: command_line {"text": "rectang 0,0 100,60"}, then execute {"command":"circle", "params":{"center":[10,10],"radius":4}}, then a dimension, then inspect_drawing {} to confirm the geometry is actually there, then render {}. That is a verification loop, not a guess.

And because CADCraft has real parametric constraints - geometric and dimensional constraints, AUTOCONSTRAIN, PARAMETERS with expressions and conflict detection that re-solves after every edit - an agent can change one dimension and have the drawing re-solve instead of a human redrawing it.

CADCraft is 2D-focused on purpose: it will not open STEP, STL, IGES, 3MF, DGN or DWF, its DWG save drops 3D solids and proxy objects, and SHX fonts and .ctb / .stb plot styles are not read. Its own docs state that DXF is read up to R12-2018 and written at R2000, and DWG (R13-2018) is handled by converting through a third-party crate. Which brings us to the part of this that actually hurts.

ArtCraft: MCP/CLI-first, and what that design decision buys you

The project's name is CADCraft; the org is ArtCraft (GitHub account storytold, whose display name is literally " ArtCraft " and which publishes the app list at getartcraft.com).

Two things to be careful of when searching, because they waste people's time: there is a separate storytold/artcraft media "crafting engine" that is not CAD, and the domain cadcraft.org says on its own page that it is an independent guide, not the official site. Official sources are the GitHub repo and getartcraft.com.

The design signal I want to take from ArtCraft's CADCraft is the order of the interfaces: a headless CLI whose conventions are specified in a numbered RFC, an MCP server that is a mode of that same binary, a JSON control channel, and only then a GUI with --control as an explicit escape hatch to drive the running app.

Their trademark policy reinforces the point: the code license (MIT OR Apache-2.0) does not cover the ArtCraft name or logos, and forks are required to remove them, so what they are protecting is the contract, not the code.

That

Read on DEV Community ↗ ← Back to News

Comments

No comments yet. Start the discussion.