Every FreeCAD MCP tool returns Failed to get RPC status: [Errno 111] Connection refused while nc says the RPC port is open. The port is held by a Tailscale proxy listener, not by FreeCAD. The fix is to start the RPC server inside the FreeCAD GUI on the cad host. Diagnostic runbook below.
The trap in one line
On a
tailscale serve/ userspace-networking node, an open port proves the proxy is up — never that the backend is up.
Symptom
Every FreeCAD MCP tool call (both routes, see below) fails identically:
Failed to get RPC status: [Errno 111] Connection refused
Errno 111 is Linux ECONNREFUSED. macOS uses 61. Seeing 111 from a Mac client proves the refusal is generated on the remote Linux host, not locally — so this is not a Mac networking, DNS, or MCP-client problem. Stop debugging the laptop.
Both access routes fail together (same backend)
| Route | Address |
|---|---|
Direct MCP server in ~/.claude.json (project /Users/levander) | {"type":"http","url":"https://cad.taild4189d.ts.net:8443/mcp"} |
Indirect, via the aperture connector | tools appear as mcp__aperture__freecad_* |
Both proxy to the same FreeCAD RPC backend, so both go down together. Failing over from one to the other is not a workaround and tells you nothing new.
The nc false positive
nc -z cad.taild4189d.ts.net 9875 # reports OPEN — and is MEANINGLESS hereThe port answers the TCP handshake, so nc -z calls it open. FreeCAD can still be completely absent. Per 2026-08-31-tailnet-plaintext-port-hardening, tailscaled --tun=userspace-networking unconditionally forwards inbound TCP on the node’s tailnet IP to 127.0.0.1 on the same port, independently of any tailscale serve mount. That forwarder accepts the connection first and only then tries the backend — so it reports “open” even when nothing is bound on 127.0.0.1:9875. (cad:9875 is the exact raw-forwarder surface that note flagged as left open for follow-up.)
The discriminating probe — speak a protocol, don’t just knock
Connect to 9875 and actually say something. All three of these were tried on 2026-09-02 and all three failed:
| Probe | Result |
|---|---|
| XML-RPC over http | RemoteDisconnected |
| XML-RPC over https | RemoteDisconnected |
| Raw TLS handshake | SSLEOFError: UNEXPECTED_EOF_WHILE_READING |
The signature is accept-then-close with zero bytes of response, regardless of which protocol is spoken. A live XML-RPC server would answer the http probe; a live TLS endpoint would complete a handshake. Answering nothing to everything is the fingerprint of a proxy whose backend is dead.
Contrast with port 8443, which completes a real TLS 1.3 handshake. So the MCP server process itself is genuinely running and serving — only the FreeCAD RPC behind it is dead. That narrows the fault to exactly one layer.
# 1. Does the MCP front door do real TLS? (expect: yes, TLS 1.3)
openssl s_client -connect cad.taild4189d.ts.net:8443 -brief </dev/null
# 2. Does 9875 speak XML-RPC? (expect on failure: RemoteDisconnected)
python3 -c 'import xmlrpc.client as x; print(x.ServerProxy("http://cad.taild4189d.ts.net:9875").ping())'For Agents
Decision rule:
Errno 111+ncopen + accept-then-close on 9875 + working TLS on 8443 ⇒ FreeCAD GUI/RPC is down on thecadhost. Do not re-probe, do not retry the tools, do not switch between the direct MCP server and theapertureconnector. It needs a human at the CAD host.
Fix
Open FreeCAD on the cad host and start the RPC server from the freecad-mcp addon workbench — the “Start RPC Server” action. The XML-RPC server runs on the GUI thread (that is what makes designs appear live in noVNC, see 2026-08-26-freecad-cad-workstation), so no GUI ⇒ no RPC ⇒ every MCP tool fails.
cadis NOT reachable over Tailscale SSH
cad(100.120.203.1) shows online intailscale status, but it is not in the Tailscale-SSH-enabled machine list — only telep-mainframe and telep-router are. “Online in the tailnet” and “SSH-able” are different facts; check the SSH-enabled list, not the online list.✅ CORRECTED 2026-09-05 — this does NOT mean the box needs a person on site.
ssh 100.120.203.1works fine.cadis not a separate machine: it is a userspacetailscaledsidecar node running on telep-mainframe, and every per-service sidecar (cad,knowledgebase,drive,chatcut,orcaslicer,bambuddy, …) lives on that one bare-metal host — so SSHing to any of their tailnet IPs lands on telep-mainframe, which is where the docker stack is anyway. (Consistent with the raw forwarder in 2026-08-31-tailnet-plaintext-port-hardening: inbound TCP on the node’s tailnet IP goes to127.0.0.1on the same port, so:22hits the mainframe’s own sshd.) An entire FreeCAD recovery was performed remotely this way on 2026-09-05 — see 2026-09-05-freecad-mcp-502-dead-container-and-qt-event-loop-wedge.
Per 2026-08-26-freecad-cad-workstation the cad node is a userspace tailscaled sidecar in front of the FreeCAD docker compose stack, and the addon is configured with auto_start_rpc=true — meaning RPC is supposed to come up with the GUI on every boot. A refused RPC therefore means the GUI/container isn’t running at all, not that someone forgot to click the button. The compose-level recovery commands (docker compose ps / restart, docker logs freecad) live in that note.
The next failure mode is NOT this one
Once the container is back and
get_rpc_statusanswers, you can land in a second, different fault: status reportshealthybut everyexecute_codetimes out withGUI dispatch timed out after 90s, because a modal Document Recovery dialog owns the GUI thread. There, a restart is the wrong move. See 2026-09-02-freecad-mcp-gui-dispatch-timeout-modal-dialog. The discriminator is whetherget_rpc_statusitself fails (→ restart) or succeeds (→ dismiss the dialog).
Related
- 2026-09-02-freecad-mcp-gui-dispatch-timeout-modal-dialog — the next chapter of this same session: RPC healthy but GUI thread blocked by a modal dialog, and why
docker execcannot launch FreeCAD - 2026-09-05-freecad-mcp-502-dead-container-and-qt-event-loop-wedge — the third failure mode, three days later: an HTTP 502 on
:8443(deadfreecad-mcpcontainer whoserestart: unless-stoppednever fired), the correction that dismissing the dialog is not always enough, and the proof thatcadcan be managed remotely - 2026-08-26-freecad-cad-workstation — the FreeCAD + noVNC + MCP architecture, port map, and restart commands
- 2026-08-31-tailnet-plaintext-port-hardening — why the userspace-networking raw forwarder makes
nclie about backend health - 2026-08-31-telep-kb-mcp-server — the sibling MCP-over-tailnet gotcha (
421 Invalid Host headerbehindtailscale serve) - 2026-08-26-cad-designer-agent — the on-prem agent that drives this MCP (also blocked by this failure)
- service-unreachable · runbooks-index
- LOG · TOPICS