mcp-freecad
Grants AI agents headless access to FreeCAD via the command-line freecadcmd: inspecting CAD models (dimensions, volume, watertightness, validity), converting between CAD and mesh formats (STEP, IGES, BREP, FCStd, STL, 3MF, OBJ, PLY), generating 2D profiles as SVG/DXF for laser cutting, and running arbitrary FreeCAD Python scripts.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@mcp-freecadCheck if bracket.step is watertight and convert it to STL for 3D printing."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
mcp-freecad
Servidor MCP que dá ao agente (Claude Code, Claude Desktop e outros clientes MCP)
acesso ao FreeCAD sem interface gráfica: inspecionar um modelo, converter entre
formatos CAD e de malha, tirar perfis 2D para corte a laser e rodar scripts Python do
FreeCAD. Toda operação roda no freecadcmd, o FreeCAD de linha de comando, então
funciona em servidor e em CI, sem o FreeCAD aberto. Linux e macOS.
Para que serve
Impressão 3D (FDM): conferir se a peça é estanque (watertight), medir e converter STEP em STL ou 3MF com a fineza escolhida.
Corte a laser: gerar DXF ou SVG em mm a partir de um corte do modelo 3D.
Gabinetes para eletrônica: ler o STEP da placa exportado pelo KiCad, pegar as dimensões e modelar o gabinete em volta (receita mais abaixo).
Automação: tudo é headless, então roda em CI.
Related MCP server: root-ext-cad
Requisitos
FreeCAD 1.0 ou superior; use a 1.1.4 ou mais nova (é a testada). A 1.1.4 corrige duas falhas de segurança disparadas ao abrir um
.FCStdmalicioso, e todas as versões anteriores são afetadas, segundo as notas da versão. Isso importa para quem abre arquivos de terceiros comdoc_inspectoudoc_export.Python 3.11 ou superior e uv.
Linux ou macOS. Windows não é suportado.
Instalar o FreeCAD
O servidor procura o freecadcmd sozinho (ordem: MCP_FREECAD_CMD, PATH, caminhos
conhecidos, Flatpak, Snap). A tool freecad_version diz qual comando ele achou e por
qual regra.
Linux: AppImage oficial
Recomendado: é o que foi testado.
mkdir -p ~/.local/opt/freecad && cd ~/.local/opt/freecad
# Baixe, em https://github.com/FreeCAD/FreeCAD/releases (release 1.1.4), o AppImage
# (~780 MB) e o arquivo de checksum ao lado dele:
# FreeCAD_1.1.4-Linux-x86_64-py311.AppImage
# FreeCAD_1.1.4-Linux-x86_64-py311.AppImage-SHA256.txt
sha256sum -c FreeCAD_1.1.4-Linux-x86_64-py311.AppImage-SHA256.txt
chmod +x FreeCAD_1.1.4-Linux-x86_64-py311.AppImage
ln -sf FreeCAD_1.1.4-Linux-x86_64-py311.AppImage FreeCAD.AppImageO servidor procura ~/.local/opt/freecad/FreeCAD.AppImage e o chama como
FreeCAD.AppImage freecadcmd. Teste:
~/.local/opt/freecad/FreeCAD.AppImage freecadcmd -c "import FreeCAD; print(FreeCAD.Version()[:3])" < /dev/nullDeve imprimir ['1', '1', '4']. Duas observações:
Nunca rode o AppImage sem argumentos. Sem display ele tenta abrir a GUI e falha. O
< /dev/nulltambém importa: com o stdin aberto ofreecadcmdespera no console.Se o AppImage reclamar de FUSE, instale o
libfuse2t64(Ubuntu 24.04 ou mais novo; nas versões anteriores o pacote élibfuse2). A alternativa é extrair o AppImage, o que dispensa o FUSE e ainda deixa cada chamada mais rápida (cerca de 0,1 s em vez de 0,3 s, porque nada é montado a cada vez):cd ~/.local/opt/freecad ./FreeCAD.AppImage --appimage-extract # cria squashfs-root/, cerca de 3 GBO servidor não procura a pasta extraída: aponte
MCP_FREECAD_CMDpara ela, com caminho absoluto, por exemplo/home/USUARIO/.local/opt/freecad/squashfs-root/AppRun freecadcmd.
Linux: Flatpak ou Snap
Alternativas não testadas nesta versão. O servidor as detecta sozinho, ou você aponta o comando:
Pacote | Instalar |
|
Flatpak |
|
|
Snap |
|
|
Esses pacotes rodam isolados e, em geral, não enxergam o /tmp do host, onde o
servidor grava os arquivos de job. Se as operações falharem com MF-RUN-1, defina TMPDIR no
ambiente do servidor para uma pasta dentro do home (no Snap, prefira uma que não comece
com ponto) e mantenha os modelos no home. O Flatpak oficial declara acesso ao sistema
de arquivos do host (--filesystem=host), mas o /tmp continua privado. Confira a versão
com freecad_version: esses pacotes podem estar atrás da 1.1.4.
macOS
Duas opções:
DMG oficial (arm64 para Apple Silicon, x86_64 para Intel) em https://github.com/FreeCAD/FreeCAD/releases; arraste o app para
/Applications.brew install --cask freecad
O binário headless é /Applications/FreeCAD.app/Contents/Resources/bin/freecadcmd. Em
Contents/MacOS/ fica só o launcher da GUI, que não serve sem display. O binário não
está no PATH, nem com o cask do Homebrew, e o servidor o encontra sozinho. Ele procura
em /Applications e em ~/Applications, primeiro Contents/Resources/bin/freecadcmd e,
como fallback para versões antigas, Contents/MacOS/FreeCADCmd. Na primeira execução o
macOS pode pedir para autorizar o app: abra o FreeCAD uma vez pelo Finder e autorize.
Teste:
/Applications/FreeCAD.app/Contents/Resources/bin/freecadcmd -c "import FreeCAD; print(FreeCAD.Version()[:3])" < /dev/nullInstalar o servidor
Dentro da pasta do repositório:
uv sync
uv run python -c "from mcp_freecad import freecad_cmd; print(freecad_cmd.version())"O segundo comando roda o FreeCAD de verdade e deve imprimir a versão, o Python embutido
e o comando usado. Se terminar com MF-CMD-1, o FreeCAD não foi encontrado: veja
MCP_FREECAD_CMD abaixo.
Registrar no cliente MCP
Claude Code
Na pasta do repositório:
claude mcp add freecad -- uv --directory "$(pwd)" run mcp-freecadClaude Desktop
O Claude Desktop não herda o PATH do shell, então o command precisa ser o caminho
absoluto do uv. Descubra com which uv. Exemplos: /opt/homebrew/bin/uv (macOS com
Apple Silicon e Homebrew) e /home/USUARIO/.local/bin/uv (Linux com o instalador
oficial; o JSON não expande ~). No macOS o arquivo é
~/Library/Application Support/Claude/claude_desktop_config.json:
{
"mcpServers": {
"freecad": {
"command": "/opt/homebrew/bin/uv",
"args": ["--directory", "/CAMINHO/ABSOLUTO/mcp-freecad", "run", "mcp-freecad"]
}
}
}Para passar variáveis de ambiente, acrescente ao bloco freecad (vale também para o
.mcp.json do Claude Code):
"env": { "MCP_FREECAD_ALLOWED_PATHS": "/Users/voce/projetos:/tmp" }Tools
Os caminhos aceitam ~ e são validados contra MCP_FREECAD_ALLOWED_PATHS. As unidades
são sempre mm.
Tool | Obrigatórios | Opcionais (padrão) |
| ||
|
| |
|
|
|
|
|
|
|
|
|
Formatos de entrada: .FCStd, .step/.stp, .iges/.igs e .brep em todas as tools de
documento. As malhas .stl, .obj, .3mf e .ply valem em doc_inspect e doc_export,
mas não em doc_export_2d.
freecad_version
Primeira chamada de qualquer sessão: confirma que o FreeCAD foi achado.
{}Retorna version, python, command (o comando usado) e discovered_by (a regra que
o achou: env:MCP_FREECAD_CMD, PATH:freecadcmd, known-path:<caminho>, flatpak
ou snap).
doc_inspect
Dimensões, volume, validade e se a peça é estanque.
{ "path": "~/projetos/placa/placa.step" }{
"kind": "solid",
"units": "mm",
"bbox": { "x": 40.0, "y": 30.0, "z": 20.0, "min": [0, 0, 0], "max": [40, 30, 20] },
"objects_total": 1,
"objects": [
{
"name": "Part__Feature", "label": "Caixa", "type": "Part::Feature",
"bbox": { "x": 40.0, "y": 30.0, "z": 20.0, "min": [0, 0, 0], "max": [40, 30, 20] },
"volume_mm3": 24000.0, "area_mm2": 5200.0, "solids": 1, "faces": 6, "is_valid": true
}
],
"checks": { "watertight": true, "all_valid": true }
}kindésolid(STEP, IGES, BREP),document(.FCStd) oumesh.Posições e
bboxestão no espaço global do documento: oPlacementdosApp::Partque contêm cada objeto é aplicado, inclusive quando eles estão aninhados. Obboxdo topo cobre todos os objetos: é o tamanho da peça ou da montagem.objectstraz os objetos finais (os que nenhuma outra feature consome), até 100;objects_totaldiz quantos existem etruncated: trueaparece quando há corte. Usenameoulabelno parâmetroobjectsdas outras tools.Em
checks,watertighté o que decide se a peça imprime em FDM. Numa montagem um objeto solto derruba o veredito;not_watertighteinvalidlistam quais (até 20).Malha devolve
meshno lugar deobjects:facets,points,is_solid,non_manifold,self_intersections,volume_mm3,area_mm2ebbox.
doc_export
Converte para o formato da extensão de out_path.
{
"path": "~/projetos/caixa.step",
"out_path": "~/projetos/caixa.3mf",
"linear_deflection": 0.05
}Saídas:
.step/.stp,.iges/.igs,.brep,.FCStde malhas.stl,.3mf,.obje.ply.Para malha a partir de sólido,
linear_deflection(mm) eangular_deflection_degcontrolam a fineza. Menor dá mais facetas e arquivo maior.objectsexporta só os objetos pedidos, pornameoulabel.Em STEP, IGES e BREP cada objeto sai como peça solta, já na posição global, e a hierarquia de montagem não é preservada.
.FCStdsemobjectsguarda o documento inteiro.Malha converte para outra malha ou para
.FCStd, nunca para.step,.igesou.brep. A saída nunca pode ser o próprio arquivo de entrada.
Retorna out_path, bytes e, quando a saída é malha, facets.
doc_export_2d
Perfil 2D em .svg ou .dxf, em mm.
{
"path": "~/projetos/tampa.step",
"out_path": "~/projetos/tampa.dxf",
"mode": "section",
"axis": "z",
"offset": 1.5
}mode: "section"corta o modelo pelo planoeixo = offsete exporta os contornos. É o modo para laser. O DXF sai plano, em Z=0, comLINE,ARCeCIRCLEde verdade.mode: "projection"exporta a vista com arestas visíveis e silhueta, sem linhas ocultas. Serve de preview e de desenho;offseté ignorado.O desenho nunca sai espelhado:
zé a vista de topo (eixos x, y do modelo),ya frontal (x, z) exa lateral direita (y, z). As coordenadas são as do modelo nos dois eixos que sobram, sem recentrar; a do eixo do corte é descartada.Corte que não toca o modelo devolve erro com a faixa do modelo no eixo.
Exige sólido ou documento; malha não é aceita.
Retorna out_path, bytes e wires (contornos no section, arestas na projection).
part_run_script
A válvula de escape: roda Python do FreeCAD headless para tudo que as outras tools não cobrem (roscas, gabinetes paramétricos, peças de jogo).
{
"script": "b = Part.makeBox(40, 30, 20)\nb.exportStl(OUT_DIR + '/caixa.stl')\nprint(b.Volume)",
"out_dir": "~/projetos/saida"
}O script já tem no namespace
doc(documento novo),OUT_DIR(string),FreeCAD(também comoApp) ePart. Qualquer outro módulo (Mesh,Sketcher,PartDesign) éimportseu.Retorna
stdout(o que o script imprimiu),files(arquivos novos ou modificados emout_dir) eobjects(objetos finais dedoc).Erro no script volta como
{"error": ...}com o traceback das linhas do script e o stdout até o erro. O servidor continua de pé.Não é sandbox. O script roda com as permissões do seu usuário e pode ler e escrever onde você pode.
MCP_FREECAD_ALLOWED_PATHSsó valida os argumentos das tools.Cada chamada é um processo novo: nada persiste de uma chamada para a outra. Grave em
OUT_DIRe releia com as outras tools.
Erros
Toda falha volta como {"error": "[MF-<área>-<n>] mensagem"}:
Código | Significa |
|
|
| o |
| estourou o timeout |
| a operação falhou dentro do FreeCAD: arquivo inválido, extensão não suportada, objeto não encontrado, erro no script |
| caminho fora de |
| argumento inválido |
Variáveis de ambiente
Variável | Efeito |
| Comando do |
| Prefixos separados por |
| Timeout padrão por operação, em segundos. Padrão 120; sempre limitado a 5–900 |
O servidor também respeita TMPDIR para os arquivos de job.
Receita: gabinete a partir do KiCad
KiCad para STEP e DXF, no terminal (ou peça ao agente para rodar):
kicad-cli pcb export step --force --subst-models -o ~/projetos/placa/placa.step ~/projetos/placa/placa.kicad_pcb kicad-cli pcb export step --force --board-only -o ~/projetos/placa/placa_so_placa.step ~/projetos/placa/placa.kicad_pcb kicad-cli pcb export dxf --layers Edge.Cuts --output-units mm --drill-shape-opt 0 --mode-single -o ~/projetos/placa/contorno.dxf ~/projetos/placa/placa.kicad_pcbO primeiro traz a placa com os componentes. O
--subst-modelstroca cada modelo VRML (.wrl) pelo.stepde mesmo nome; sem ele, os modelos.wrlnão entram no STEP e okicad-cliavisa que não pode usar VRML. Quando os footprints já apontam para.step, o flag não muda nada (medido no KiCad 10.0.5).O segundo traz só a placa, sem componentes.
O terceiro é o contorno 2D. O DXF do
kicad-clisai em polegadas por padrão, daí o--output-units mm. O--drill-shape-opt 0tira os círculos dos furos de pads e vias.O STEP sai nas coordenadas da folha do KiCad, então a placa não fica na origem. Use o
bbox.mindodoc_inspectcomo deslocamento, ou escolha a origem com--drill-origin,--grid-originou--user-origin.
Medir a placa com
doc_inspectnos dois STEPs. Obboxdo topo cobre todas as peças eobjectslista cada uma pelolabel. Compare os dois STEPs para separar o tamanho da placa do que sobra dela. No demopic_programmerdo KiCad 10, a placa tem 160,02 x 99,06 x 1,51 mm e, com os componentes, 168,02 x 99,06 x 19,37 mm: um conector passa 8 mm do contorno e os terminais saem 4,7 mm abaixo da placa. Uma placa real de 316 peças levou 8 s.Modelar o gabinete com
part_run_script, usando obboxcomo parâmetro. Este exemplo faz a base, uma caixa aberta em cima com parede e folga ao redor da placa:W, D, H = 60.0, 40.0, 15.0 # bbox da placa (mm), vindo de doc_inspect wall, gap = 2.0, 1.0 # parede e folga entre a placa e a parede V = FreeCAD.Vector m = wall + gap casca = Part.makeBox(W + 2 * m, D + 2 * m, H + gap + wall, V(-m, -m, -wall)) cavidade = Part.makeBox(W + 2 * gap, D + 2 * gap, H + gap + 1, V(-gap, -gap, 0)) base = casca.cut(cavidade) # aberta em cima base.exportStep(OUT_DIR + "/gabinete_base.step") base.exportStl(OUT_DIR + "/gabinete_base.stl")Validar e fabricar.
doc_inspectno STL confirmawatertighte o tamanho (66 x 46 x 18neste exemplo). Para imprimir,doc_exportdo STEP em.3mf; a fineza (linear_deflection) só vale a partir de um sólido, não de uma malha. Para uma tampa cortada a laser, modele a chapa e usedoc_export_2dcommode: "section"no meio da espessura:{ "path": "~/projetos/saida/tampa.step", "out_path": "~/projetos/saida/tampa.dxf", "mode": "section", "axis": "z", "offset": 1.5 }
Limitações
Sem render PNG headless. Use
doc_export_2dem modoprojectioncomo preview.Projeção: o desenho tem arestas visíveis e silhueta, sem linhas ocultas. Em vista lateral de cilindros o círculo visto de borda sai como spline degenerada, com sobreposição. Para corte a laser use sempre
section.Testado só em Linux com o AppImage 1.1.4. As regras de descoberta de macOS, Flatpak e Snap existem e têm testes unitários, mas não foram exercitadas com o FreeCAD real. O caminho do macOS vem da leitura do código de empacotamento do 1.1.4, não de uma execução em Mac.
Windows não é suportado: o timeout usa grupos de processo POSIX.
App::Linknão é seguido (montagens do Assembly Workbench): odoc_inspectmostra o objeto original na posição dele e ignora as instâncias. Usepart_run_script.Malha não vira sólido:
.stl,.obj,.3mfe.plynão convertem para.step,.igesou.brep. Objetos de malha dentro de um.FCStdsão ignorados.IGES costuma trazer superfícies sem sólido; nesse caso
watertightsaifalse.Montagens grandes custam: inspecionar um STEP de 73 MB com 1164 peças levou 45 s. Acima de 120 s aumente
MCP_FREECAD_TIMEOUT_S(máximo 900).doc_inspectdetalha no máximo 100 objetos por chamada.doc_exportsobrescreve em silêncio uma saída que já exista (menos a própria entrada).
Desenvolvimento
uv sync
uv run ruff check .
uv run pytest -q # unitários + integração
uv run pytest -q -m "not integration" # só o que não precisa do FreeCADOs testes de integração rodam o freecadcmd de verdade e são pulados quando o FreeCAD
não é encontrado. tests/test_server_lists_tools.py sobe uv run mcp-freecad e fala
MCP por stdio com o cliente do SDK.
src/mcp_freecad/
server.py as 5 tools e _guard()
freecad_cmd.py descoberta do binário, job JSON, subprocess e timeout
runner.py roda DENTRO do freecadcmd; só stdlib e módulos do FreeCAD
paths.py validação de caminhos
errors.py erros MF-<área>-<n>
docs/adr/ decisões de arquiteturaA decisão central (por que um subprocess por chamada, por que o resultado vai por arquivo) está no ADR 0001.
Licença
MIT. Veja LICENSE.
Available Tools
5 toolsdoc_exportA
Converte um modelo para o formato da extensão de out_path.
Saídas: .step/.stp, .iges/.igs, .brep, .FCStd e malhas .stl/.3mf/.obj/.ply. Ao gerar
malha a partir de sólido, linear_deflection (mm) e angular_deflection_deg
controlam a fineza: valores menores dão mais facetas. objects filtra por Name ou
Label; sem ele exporta todos os objetos finais. Malha não vira .step/.iges/.brep,
só .FCStd ou outra malha. Não sobrescreve a própria entrada.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | ||
| objects | No | ||
| out_path | Yes | ||
| linear_deflection | No | ||
| angular_deflection_deg | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations supplied, the description carries the full burden and does disclose meaningful traits: it will not overwrite the input, mesh conversion is restricted to .FCStd or other mesh formats, and deflection values trade off fineness against facet count. It omits whether an existing out_path is overwritten and any permission requirements.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The format-selection rule is front-loaded in the first sentence, followed by a compact list of outputs and the two mesh knobs. Every sentence carries information, though the flow is a bit cramped with several short fragments.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 5-parameter export tool with no annotations, the description covers format routing, filtering, mesh quality and the key non-destructive constraint. An output schema exists so return values need not be explained; the lingering gap is the meaning of the required `path` parameter.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description must compensate, and it does for most parameters: out_path's extension picks the format, objects matches Name or Label, and both deflection params are given meaning, units and a concrete direction of effect. Only `path` (the input model) is left unexplained.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource ('Converte um modelo') and enumerates the target formats selected by out_path's extension, so the agent knows exactly what the tool produces. It does not explicitly contrast itself with the sibling doc_export_2d, leaving the 2D-vs-3D split to inference from names.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is only implied: the agent can infer that mesh output cannot target .step/.iges/.brep and that omitting `objects` exports everything. There is no explicit when-to-use statement or reference to an alternative sibling such as doc_export_2d for 2D output.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
doc_export_2dA
Gera .svg ou .dxf em mm a partir de um sólido: perfil de corte a laser ou desenho.
mode="section" corta o modelo pelo plano eixo=offset e exporta os contornos
(para laser, use este). mode="projection" exporta a vista com arestas visíveis e
silhueta, boa como preview ou desenho; offset é ignorado. O desenho nunca sai
espelhado: z é a vista de topo (x,y), y a frontal (x,z) e x a lateral direita
(y,z). Exige sólido ou documento (não aceita malha). wires no retorno é o número
de contornos (section) ou de arestas (projection).
| Name | Required | Description | Default |
|---|---|---|---|
| axis | No | z | |
| mode | No | projection | |
| path | Yes | ||
| offset | No | ||
| objects | No | ||
| out_path | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and delivers: the input must be a solid or document and meshes are rejected, `offset` is silently ignored under projection, orientation is never mirrored (with the axis-to-view mapping), and output units are mm. It even describes what `wires` counts in the result, far beyond what structured fields provide.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core action, then mode semantics, then constraints, then return meaning. Dense but every sentence carries new information and nothing is redundant.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists so return values needn't be spelled out, yet the description supplies mode rules, axis conventions, input constraints and the meaning of `wires`. Only the file-path and object-selection parameters remain unaddressed, which is a minor gap for an otherwise complete definition.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. It thoroughly explains mode, axis (z=top, y=frontal, x=right side) and offset, but leaves path, out_path and especially objects completely undefined in both schema and description.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource (generates .svg/.dxf in mm from a solid) and then distinguishes its two operating modes with concrete behavior, so an agent can identify it instantly without opening the schema. The '2D from solid' framing also implicitly separates it from the generic doc_export sibling.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit mode-selection guidance ('para laser, use este' for section; projection as preview/drawing), which is the main decision an agent must make. It does not, however, compare itself against the sibling doc_export or state when NOT to use this tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
doc_inspectA
Abre um modelo e devolve dimensões, volume, validade e se é estanque (watertight).
Aceita .FCStd, .step/.stp, .iges/.igs, .brep e malhas .stl/.obj/.3mf/.ply. Unidades
sempre em mm. Para sólidos e documentos lista os objetos finais (até 100;
objects_total diz quantos existem) com name e label: qualquer um dos dois serve
no parâmetro objects de doc_export e doc_export_2d. Para malha devolve mesh
(facetas, is_solid, non_manifold, self_intersections). checks.watertight é o que
decide se a peça imprime em FDM.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full behavioral burden and does well: it discloses the 100-object cap with `objects_total`, that units are always mm, the accepted file formats, and that `checks.watertight` is the FDM-printability decision. It never explicitly states this is a non-mutating read, which is the one gap given zero annotation coverage.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Every sentence earns its place: purpose first, then accepted inputs, then return contract, then the downstream consumer of the object names. Dense but zero filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be documented — yet the description still maps the key return fields (`mesh`, `objects_total`, `checks.watertight`) and their significance, making it more than sufficient for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0% and the single `path` param is undocumented in the schema, but the description compensates by enumerating accepted formats (.FCStd, .step/.stp, .iges/.igs, .brep, .stl/.obj/.3mf/.ply) and stating that units are mm — directly useful semantics for supplying a valid path.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource (opens a model and returns dimensions, volume, validity, watertightness) and clearly distinguishes itself from the export siblings by noting that its name/label output feeds doc_export and doc_export_2d's `objects` parameter. An agent immediately knows this is the inspection step vs. the export step.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Cross-references the alternatives explicitly: the returned `name`/`label` values are usable in doc_export and doc_export_2d, which implies inspect-first workflow. It does not spell out an explicit 'do not use this to modify' exclusion, so it falls just short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
freecad_versionA
Versão do FreeCAD, do Python embutido e qual comando o servidor está usando.
Primeira coisa a chamar quando algo não funciona: confirma que o freecadcmd foi encontrado e por qual regra (env, PATH, caminho conhecido, flatpak, snap).
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the behavioral burden, and it does disclose useful behavior beyond a plain version string: it reports which resolution rule matched (env, PATH, known path, flatpak, snap). The read-only, non-destructive nature is self-evident from the diagnostic framing, but it is never stated explicitly.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short lines: the first states what is reported, the second front-loads the diagnostic use case and the resolution rules. No filler, and the most actionable instruction is placed immediately.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so the description need not describe return values, and with zero parameters there is no argument documentation burden. Purpose, usage trigger, and the shape of the diagnostic result are all covered for a simple zero-arg probe.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so the baseline is 4; there are no argument semantics for the description to clarify. Schema coverage is trivially 100%.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Names a specific subject (FreeCAD version), an additional resource (embedded Python version), and the resolved command the server is using. It is unmistakably a diagnostic/inspection tool and none of the siblings (doc_inspect, doc_export, doc_export_2d, part_run_script) overlap with it.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives an explicit usage trigger: 'First thing to call when something doesn't work'. That is a clear when-to-use directive, though it does not enumerate when-not-to-use or name any alternative (there is no comparable sibling anyway).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
part_run_scriptA
Roda um script Python no FreeCAD headless: a válvula de escape da API completa.
Serve para modelar o que as outras tools não cobrem (roscas, gabinetes
paramétricos, peças de jogo). O script já tem no namespace doc (documento novo),
OUT_DIR (str) e os módulos FreeCAD (também como App) e Part; qualquer outro
(Mesh, Sketcher, PartDesign...) é import seu. Grave o que quiser em OUT_DIR, por
exemplo shape.exportStl(OUT_DIR + "/peca.stl"). Retorna stdout,
files (novos ou modificados em out_dir) e objects (objetos finais de doc).
Erro no script volta como {error} com traceback e stdout. timeout_s vale de 5 a 900
(padrão: MCP_FREECAD_TIMEOUT_S ou 120). ATENÇÃO: o script roda com as permissões do
usuário; MCP_FREECAD_ALLOWED_PATHS valida só os argumentos, não isola o script.
| Name | Required | Description | Default |
|---|---|---|---|
| script | Yes | ||
| out_dir | Yes | ||
| timeout_s | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does so: it documents the pre-populated namespace (doc, OUT_DIR, FreeCAD/App, Part, imports required for Mesh/Sketcher/PartDesign), the return payload (stdout, files, objects), the failure shape ({error} with traceback and stdout), the timeout range and default, and a security caveat that the script runs with user permissions and is not isolated by MCP_FREECAD_ALLOWED_PATHS.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core purpose, and every sentence adds operational value (namespace, output, errors, timeout, security). It is dense and parenthetical-heavy, but there is no filler; only minor tightening is possible.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a high-complexity arbitrary-code-execution tool with 3 params at 0% schema coverage, the description supplies invocation environment, output handling, error contract, timeout bounds and the critical sandboxing caveat. An output schema exists, yet the extra return-format detail reinforces rather than pads.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate, and it does for all three parameters: `script` (what is pre-injected, what must be imported), `out_dir` (exposed as OUT_DIR, output files land there), and `timeout_s` (valid 5–900, defaults to MCP_FREECAD_TIMEOUT_S or 120). Nothing is left undocumented.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('Roda um script Python no FreeCAD headless') and immediately frames its niche against the sibling set ('a válvula de escape da API completa', covering what other tools don't: threads, parametric enclosures, game pieces). An agent can tell this apart from doc_inspect/doc_export without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives clear positive selection criteria — use it for geometry the other tools don't cover, with concrete examples (roscas, gabinetes paramétricos, peças de jogo). No explicit when-not-to-use or named alternative is given, so it stops short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
5 tool updates
v0.1.0- First observed
doc_export - First observed
doc_export_2d - First observed
doc_inspect - First observed
freecad_version - First observed
part_run_script
TDQS
Scored across 5 tools
Each tool has a clearly distinct role: version diagnostics, inspection, 3D export, 2D export, and a scripting escape hatch. The only mild overlap is between doc_export and doc_export_2d, but the descriptions make the 3D-vs-2D boundary explicit (extension-based vs .svg/.dxf).
All names are snake_case and readable, but the prefixes are inconsistent: freecad_, doc_, part_, and doc_export_2d adds a numeric suffix. The doc_* family is coherent while freecad_version and part_run_script follow different conventions.
Five tools is well-scoped for a FreeCAD server, and each one earns its place: diagnostics, read, two write formats, and a general scripting fallback. No redundancy or filler.
The surface covers the core lifecycle (version check, inspect, 3D export, 2D export) plus an unbounded escape hatch via part_run_script that handles modeling the other tools omit. There is no dedicated create/modify tool, but scripting largely fills that gap so agent dead-ends are unlikely.
Maintenance
Related MCP Connectors
Headless CAD engine & MCP server for 2D/3D drafting, solids, DXF/SVG export, and automation.
Create, inspect, validate, and save editable 3D building scenes with Pascal's hosted MCP server.
MCP server for progressive tool usage at any scale (see https://klavis.ai)
Ovanek MCP: Model Context Protocol server for Ovanek platform tools; writes are dry-run by default.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables AI agents to programmatically build, analyze, and export 3D CAD geometry using FreeCAD through REST or MCP tools.MIT
- FlicenseAqualityBmaintenanceCAD-engineering MCP tool server for parametric modeling, DFM validation, mechanical calculations, and more. Enables code-CAD builds (build123d/CadQuery), model inspection, meshing, and mechanical calculators via MCP stdio.11-
- FlicenseNot gradedqualityCmaintenanceAn MCP server that drives a running FreeCAD session, exposing document management, modeling, inspection, snapshot, and optional workbench operations to MCP clients over stdio or authenticated remote HTTP.1-
- FlicenseNot gradedqualityBmaintenanceMCP server that exposes parametric FreeCAD operations as LLM tools, enabling natural-language-driven CAD modeling through a headless FreeCAD environment in Docker.-