A CAD program an AI can drive: what MCP is and how to use it with LinceCAD
AI assistants no longer just answer questions: they can also use programs, if the program offers them a way to do so. More and more often, that way is MCP. LinceCAD includes an MCP server, so an assistant can open a DWG, query it, draw, dimension and save while you decide which changes it may make. This article explains what MCP is, exactly what the LinceCAD server allows and what a real session looks like.
What MCP is
The Model Context Protocol is an open protocol, published by Anthropic in November 2024, for connecting AI applications with programs and data. It has two sides:
- The client is the AI application: Claude Desktop, Claude Code or another one that supports MCP.
- The server is the program that lets itself be driven. It declares tools (actions with parameters), resources (data that can be read) and prompts (ready-made instructions for common tasks).
Messages are JSON-RPC 2.0 and travel over standard input and output (the client starts the server) or over HTTP. The AI model chooses which tool to call and with what data; the client makes the call and returns the result. The server does not need to know which model is on the other side.
What the LinceCAD MCP server allows
The server starts with lince --mcp and talks over standard input and output. With LinceCAD open, you
can also enable an MCP server over HTTP, on 127.0.0.1 only. It supports protocol versions 2025-06-18,
2025-03-26 and 2024-11-05, and offers 23 tools:
| For | Tools |
|---|---|
| Drawings | list_drawings, open_drawing, new_drawing, save_drawing, drawing_summary |
| Querying | query_entities, get_entity, list_layers, list_blocks, list_block_library, get_variable, capture_view |
| Changing | create_entities, modify_entity, delete_entities, manage_layer, set_variable, add_dimension, insert_block |
| Commands and AutoLISP | run_command, eval_lisp |
| Output and control | plot_pdf, undo |
A few details that matter in practice:
capture_viewreturns a PNG image of the view, so the assistant can see the drawing and check what it has drawn.run_commandruns any command with its answers, using the English name with a leading underscore (_LINE,_DIMLINEAR), which works in any language.- Each tool is marked as read-only or destructive, so the client knows which ones to ask about.
- The resources give the summary, entities, layers, blocks and variables of each open drawing
(
lince://drawing/{id}/summary…), and the LinceCAD help pages in English and Spanish (lince://help/{lang}/{id}) as documentation for the assistant. - There are three prompts:
review_drawing(review the drawing without changing it),dimension_floor_plan(dimension a floor plan) andclean_layers(propose a layer cleanup and wait for confirmation).
How to connect it
Claude Desktop, in %APPDATA%\Claude\claude_desktop_config.json:
{
"mcpServers": {
"lince": { "command": "C:\\Program Files\\lince\\lince.exe", "args": ["--mcp"] }
}
}
Claude Code, without a window and in a project:
claude mcp add --scope project lince -- "C:\Program Files\lince\lince.exe" --mcp
With LinceCAD open: in OPTIONS, Automation tab, allow automation
and enable the MCP server over HTTP. The token (the password clients present) is in api.toml, in
%APPDATA%\lince on Windows or ~/.config/lince on Linux:
claude mcp add --transport http lince http://127.0.0.1:7341/mcp --header "Authorization: Bearer <token>"
Any other MCP client that starts a server over standard input and output is configured the same way: the command
is lince.exe and the argument, --mcp.
A real example
To see what happens underneath, we played the client with a Python script, with no AI involved: it starts
lince.exe --mcp, introduces itself, asks for the list of tools and makes the calls an assistant would
make for a request such as “create the layer MUROS (walls) in red, draw an 8 × 5 m rectangle, dimension the bottom
side and save it as planta.dwg”. Coordinates are in millimeters, and the layer for the dimension is COTAS
(dimensions).
import json, subprocess
lince = subprocess.Popen([r"C:\Program Files\lince\lince.exe", "--mcp"],
stdin=subprocess.PIPE, stdout=subprocess.PIPE)
n = 0
def send(method, params=None, notify=False):
global n
msg = {"jsonrpc": "2.0", "method": method, "params": params or {}}
if not notify:
n += 1
msg["id"] = n
lince.stdin.write((json.dumps(msg) + "\n").encode())
lince.stdin.flush()
return None if notify else json.loads(lince.stdout.readline())["result"]
def tool(tool_name, /, **args):
r = send("tools/call", {"name": tool_name, "arguments": args})
return r["content"][0]["text"]
info = send("initialize", {"protocolVersion": "2025-06-18", "capabilities": {},
"clientInfo": {"name": "blog", "version": "1"}})
send("notifications/initialized", notify=True)
print(info["serverInfo"])
print(len(send("tools/list")["tools"]), "tools")
tool("manage_layer", action="create", name="MUROS", color=1)
print(tool("create_entities", entities=[{"type": "LWPOLYLINE", "layer": "MUROS", "closed": True,
"vertices": [[0, 0], [8000, 0], [8000, 5000], [0, 5000]]}]))
tool("add_dimension", kind="linear", points=[[0, 0], [8000, 0]],
textPosition=[4000, -800], layer="COTAS")
print(tool("drawing_summary"))
print(tool("save_drawing", path=r"C:\planos\planta.dwg"))
lince.stdin.close()
lince.wait()
This is the real output with LinceCAD 0.9.8-rc3 (we only replaced the path of the saved file with the one in the example; the default drawing name is Spanish because the program ran in Spanish):
{'name': 'lince', 'title': 'LinceCAD', 'version': '0.9.8-rc3'}
23 tools
{"handles":["51"]}
{"document":{"id":1,"name":"Dibujo1.dwg","path":null,"modified":true,"active":true,"version":"AC1032","entities":2},"extents":[[0.0,-801.25],[8000.0,5000.0]],"units":0,"byType":{"DIMENSION":1,"LWPOLYLINE":1},"byLayer":{"COTAS":1,"MUROS":1},"layers":3,"blocks":0,"currentLayer":"COTAS"}
{"path":"C:\\planos\\planta.dwg","version":"AC1032"}
The summary confirms what was asked for: a polyline on layer MUROS, a dimension on COTAS and three layers in total
(0 and the two new ones). add_dimension creates the dimension by running DIMLINEAR, the
same command you would use by hand. In development testing, Claude Code acted as a real client: it created a circle
and a line and read the drawing summary.
What the user controls
- Approving changes. With LinceCAD open and confirmation enabled, every change the assistant
requests waits in the
AIACTIONSpalette until you click Accept or Reject. Accept all in this session stops asking until you close the program. Reads are not asked about. - One undo step per call. Everything a call changes is undone with a single
UNDO, and the assistant has its ownundotool. - Read-only and allowed folders. In
OPTIONSyou can block every change or limit the folders where files are opened, saved and plotted. Without a window (--mcp) nothing is asked, but those two limits still apply. - Log. The palette keeps the last 500 calls, with the time and the error, if any.
- All local. LinceCAD sends nothing outside the computer. Bear in mind, though, that what the assistant reads (summaries, entities, captures) reaches the AI service your client uses, under its terms.
Limitations
- Entities are created and queried in model space. True color is read but not written.
eval_lispfails if the routine asks the user for input (getpoint,entsel…).- The HTTP server does not keep the MCP session between requests. On Linux,
lince --mcpneeds a graphical session (orxvfb-run). - The assistant can make mistakes: review changes before accepting them and work on copies while LinceCAD is in beta.
Frequently asked questions
Do I need to know how to program? Not for MCP: you configure the client once and give instructions in plain language.
Where is the full reference? In the Automation (API and MCP) topic of the manual.
Is it an alternative to AutoCAD LT? It depends on your work; we go through it in LinceCAD vs AutoCAD LT.
The MCP server, the local API and AutoLISP come with LinceCAD, with a perpetual license. Download · See pricing · Automation and all other features.