Skip to main content
Glama

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 .FCStd malicioso, e todas as versões anteriores são afetadas, segundo as notas da versão. Isso importa para quem abre arquivos de terceiros com doc_inspect ou doc_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.AppImage

O 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/null

Deve imprimir ['1', '1', '4']. Duas observações:

  • Nunca rode o AppImage sem argumentos. Sem display ele tenta abrir a GUI e falha. O < /dev/null também importa: com o stdin aberto o freecadcmd espera 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 GB

    O servidor não procura a pasta extraída: aponte MCP_FREECAD_CMD para 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

MCP_FREECAD_CMD

Flatpak

flatpak install flathub org.freecad.FreeCAD

flatpak run --command=freecadcmd org.freecad.FreeCAD

Snap

sudo snap install freecad

/snap/bin/freecad.cmd

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:

  1. DMG oficial (arm64 para Apple Silicon, x86_64 para Intel) em https://github.com/FreeCAD/FreeCAD/releases; arraste o app para /Applications.

  2. 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/null

Instalar 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-freecad

Claude 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)

freecad_version

doc_inspect

path

doc_export

path, out_path

objects (todos), linear_deflection (0.1), angular_deflection_deg (28.6)

doc_export_2d

path, out_path

mode (projection), axis (z), offset (0), objects (todos)

part_run_script

script, out_dir

timeout_s (120, ou MCP_FREECAD_TIMEOUT_S)

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) ou mesh.

  • Posições e bbox estão no espaço global do documento: o Placement dos App::Part que contêm cada objeto é aplicado, inclusive quando eles estão aninhados. O bbox do topo cobre todos os objetos: é o tamanho da peça ou da montagem.

  • objects traz os objetos finais (os que nenhuma outra feature consome), até 100; objects_total diz quantos existem e truncated: true aparece quando há corte. Use name ou label no parâmetro objects das outras tools.

  • Em checks, watertight é o que decide se a peça imprime em FDM. Numa montagem um objeto solto derruba o veredito; not_watertight e invalid listam quais (até 20).

  • Malha devolve mesh no lugar de objects: facets, points, is_solid, non_manifold, self_intersections, volume_mm3, area_mm2 e bbox.

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, .FCStd e malhas .stl, .3mf, .obj e .ply.

  • Para malha a partir de sólido, linear_deflection (mm) e angular_deflection_deg controlam a fineza. Menor dá mais facetas e arquivo maior.

  • objects exporta só os objetos pedidos, por name ou label.

  • 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. .FCStd sem objects guarda o documento inteiro.

  • Malha converte para outra malha ou para .FCStd, nunca para .step, .iges ou .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 plano eixo = offset e exporta os contornos. É o modo para laser. O DXF sai plano, em Z=0, com LINE, ARC e CIRCLE de 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), y a frontal (x, z) e x a 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 como App) e Part. Qualquer outro módulo (Mesh, Sketcher, PartDesign) é import seu.

  • Retorna stdout (o que o script imprimiu), files (arquivos novos ou modificados em out_dir) e objects (objetos finais de doc).

  • 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_PATHS só valida os argumentos das tools.

  • Cada chamada é um processo novo: nada persiste de uma chamada para a outra. Grave em OUT_DIR e releia com as outras tools.

Erros

Toda falha volta como {"error": "[MF-<área>-<n>] mensagem"}:

Código

Significa

MF-CMD-1

freecadcmd não encontrado, ou o comando configurado não pôde ser executado

MF-RUN-1

o freecadcmd terminou sem gravar resultado (crash); a mensagem traz o final de stderr e stdout

MF-RUN-2

estourou o timeout

MF-OP-1

a operação falhou dentro do FreeCAD: arquivo inválido, extensão não suportada, objeto não encontrado, erro no script

MF-PATH-1

caminho fora de MCP_FREECAD_ALLOWED_PATHS, inexistente, saída igual à entrada, ou erro do sistema de arquivos (permissão, pasta de saída que é um arquivo)

MF-ARG-1

argumento inválido

Variáveis de ambiente

Variável

Efeito

MCP_FREECAD_CMD

Comando do freecadcmd, separado como num shell (aceita aspas). Vence qualquer descoberta. Ex.: flatpak run --command=freecadcmd org.freecad.FreeCAD

MCP_FREECAD_ALLOWED_PATHS

Prefixos separados por : onde o servidor pode ler e escrever. Padrão: home, o diretório temporário do sistema, /tmp e /var/tmp. Symlinks são resolvidos nos dois lados e a comparação é por componente de caminho (/tmpfoo não casa com /tmp)

MCP_FREECAD_TIMEOUT_S

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

  1. 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_pcb
    • O primeiro traz a placa com os componentes. O --subst-models troca cada modelo VRML (.wrl) pelo .step de mesmo nome; sem ele, os modelos .wrl não entram no STEP e o kicad-cli avisa 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-cli sai em polegadas por padrão, daí o --output-units mm. O --drill-shape-opt 0 tira 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.min do doc_inspect como deslocamento, ou escolha a origem com --drill-origin, --grid-origin ou --user-origin.

  2. Medir a placa com doc_inspect nos dois STEPs. O bbox do topo cobre todas as peças e objects lista cada uma pelo label. Compare os dois STEPs para separar o tamanho da placa do que sobra dela. No demo pic_programmer do 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.

  3. Modelar o gabinete com part_run_script, usando o bbox como 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")
  4. Validar e fabricar. doc_inspect no STL confirma watertight e o tamanho (66 x 46 x 18 neste exemplo). Para imprimir, doc_export do 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 use doc_export_2d com mode: "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_2d em modo projection como 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::Link não é seguido (montagens do Assembly Workbench): o doc_inspect mostra o objeto original na posição dele e ignora as instâncias. Use part_run_script.

  • Malha não vira sólido: .stl, .obj, .3mf e .ply não convertem para .step, .iges ou .brep. Objetos de malha dentro de um .FCStd são ignorados.

  • IGES costuma trazer superfícies sem sólido; nesse caso watertight sai false.

  • 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_inspect detalha no máximo 100 objetos por chamada.

  • doc_export sobrescreve 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 FreeCAD

Os 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 arquitetura

A 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 tools
doc_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.

ParametersJSON Schema
NameRequiredDescriptionDefault
pathYes
objectsNo
out_pathYes
linear_deflectionNo
angular_deflection_degNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.8/5.0
Behavior4/5

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.

Conciseness4/5

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.

Completeness4/5

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.

Parameters4/5

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.

Purpose4/5

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.

Usage Guidelines3/5

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).

ParametersJSON Schema
NameRequiredDescriptionDefault
axisNoz
modeNoprojection
pathYes
offsetNo
objectsNo
out_pathYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.4/5.0
Behavior5/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
pathYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.5/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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).

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.5/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
scriptYes
out_dirYes
timeout_sNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.7/5.0
Behavior5/5

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.

Conciseness4/5

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.

Completeness5/5

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.

Parameters5/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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.

  1. 5 tool updatesv0.1.0
    • First observeddoc_export
    • First observeddoc_export_2d
    • First observeddoc_inspect
    • First observedfreecad_version
    • First observedpart_run_script

TDQS

A4.1/5.0

Scored across 5 tools

Disambiguation4/5

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).

Naming Consistency3/5

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.

Tool Count5/5

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.

Completeness4/5

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

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables AI agents to programmatically build, analyze, and export 3D CAD geometry using FreeCAD through REST or MCP tools.
    MIT
  • F
    license
    A
    quality
    B
    maintenance
    CAD-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
    -
  • F
    license
    Not graded
    quality
    C
    maintenance
    An 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
    -
  • F
    license
    Not graded
    quality
    B
    maintenance
    MCP server that exposes parametric FreeCAD operations as LLM tools, enabling natural-language-driven CAD modeling through a headless FreeCAD environment in Docker.
    -