CalculiX MCP
Solver FEM de código aberto (ccx) como um servidor FastMCP, integrado ao ecossistema de agente + visualizador de navegador do CAE-Agent-Hub
Documentação
CalculiX MCP
Um servidor MCP que expõe o solver FEM de código aberto CalculiX (ccx) para clientes
MCP. O CalculiX é GPLv2, não requer licença e executa como um CLI do tipo "dispare e esqueça" —
portanto, este servidor é totalmente autônomo, sem ponte de sessão ao vivo e sem máquina de
estados de licença.
O fluxo de trabalho é: analisar um deck .inp do CalculiX/Abaqus, inspecionar suas
variáveis de projeto ajustáveis, editar um valor no local, submetê-lo ao ccx, ler os
resultados de texto (.dat) e exportar esses resultados .dat para result_mesh.json para que o
Text to CAE Viewer do repositório possa renderizar a malha e o campo de tensões.
Este é o primeiro MCP FEM com solver de código aberto no hub (a linha FEA existente parou nas referências ao FEniCS), preenchendo a lacuna observada na Issue #14.
Ferramentas
| Ferramenta | Finalidade |
|---|---|
fea_health | Relatar a disponibilidade do meshio e o executável ccx detectado. |
parse_inp | Analisar um deck .inp: nós, contagens de elementos, seções de casca/viga, materiais, cargas. |
list_design_vars_tool | Listar variáveis de projeto ajustáveis (espessura da casca, seção da viga, material E/nu/densidade, magnitude da carga), cada uma com um localizador var_id. |
modify_card_tool | Editar uma variável de projeto no local por var_id; substituição de texto puro, grava um novo .inp. |
run_solver_tool | Executar ccx -i <jobname> em um deck. O sucesso ignora o código de saída (veja abaixo). |
read_results_tool | Analisar o .dat para von Mises máximo (autocalculado), deslocamento máximo, volume, massa; para etapas *FREQUENCY também a tabela de autovalores (frequencies, n_modes). |
export_results_tool | Exportar a execução para result_mesh.json (formato do visualizador); para execuções modais, passe mode=N para exportar a forma desse modo. |
optimize_structure_tool | Otimização de dimensionamento em dois estágios (varredura LHS + descida de coordenadas): minimizar massa sujeita a limites de tensão/deslocamento (decks estáticos) ou um piso de frequência natural (decks modais, "evitar ressonância") ajustando variáveis de projeto escalares (espessura da casca, seção da viga, material, carga). Apenas modelos de casca/viga — veja Otimização. |
Contratos CalculiX conquistados com dificuldade (codificados no solver)
Estes são os motivos pelos quais este servidor não é trivial — todos a partir do comportamento público do CalculiX:
- O código de saída do ccx não é confiável —
ccxretorna 0 mesmo quando imprime*ERROR. Sucesso = sem*ERRORno stdout e o arquivo.statem uma linha de dados e sem timeout. .datnão tem von Mises — apenas 6 componentes de tensão; σ_vm é autocalculado..datnão tem volume/massa total — calculado a partir da geometria da malha ×*DENSITY.- Nunca
meshio.write— ele descarta todos os cartões e reescreveB31→B31H(corrompe o arquivo).modify_cardfaz edições de texto puro no local. - Etapas
*FREQUENCYgravam um.staapenas com cabeçalho — uma solução de autovalores não tem incrementos, então o sucesso também aceita um.datnão vazio (caso contrário, toda execução modal pareceria falha). Frequências e autovetores por modo estão no texto.dat, não apenas no.frd.
Otimização
optimize_structure_tool executa otimização de dimensionamento em dois estágios: uma varredura
grosseira de Hipercubo Latino, depois refinamento por descida de coordenadas (salto para o limite mais
bissecção repetida em direção à fronteira viável), minimizando massa sujeita a
restrições de tensão e deslocamento editando cartões escalares no local.
optimize_structure_tool(
path="examples/bracket.inp",
variables={"shell.PLATE.thickness": [2.0, 8.0]},
n_lhs=8, max_solves=18,
)
# -> best ~4.1 mm, ~-48% mass, stress < 250 MPa, displacement < 1.5 mm
Restrições de frequência ("evitar ressonância") executam o mesmo loop contra um
deck *FREQUENCY: cada avaliação é uma solução de autovalores, o modo N é lido da
tabela de autovalores .dat, e o afinamento para onde o modo se situa logo acima do seu
piso. Métricas estáticas e métricas de frequência vêm de decks estáticos e modais,
respectivamente — um conjunto de restrições incompatível torna cada ponto inviável, o que
a execução relata como um aviso de métricas ausentes.
optimize_structure_tool(
path="examples/plate_modal.inp",
variables={"shell.PLATE.thickness": [2.0, 8.0]},
constraints=[{"metric": "freq_1_hz", "op": ">", "value": 30.0}],
n_lhs=5, max_solves=24,
)
# -> best ~3.23 mm, ~-19% mass, f1 = 30.4 Hz
Escopo e honestidade:
- Apenas modelos de casca/viga. Sólidos (C3D8) não expõem cartão de geometria escalar, então não há espessura para afinar; use otimização de forma/topologia.
- Isto é otimização de dimensionamento/parâmetros, não otimização de topologia — ele afina seções, não redistribui material no espaço.
- O melhor deck é gravado ao lado da entrada como
<stem>.optimized.inp; passe-o paraexport_results_toolpara renderizar o projeto otimizado.
Análise modal
Decks *FREQUENCY funcionam com as mesmas ferramentas. O .dat carrega tudo: uma
tabela E I G E N V A L U E O U T P U T (modo, autovalor, rad/s, ciclos/s)
seguida por blocos de autovetores por modo marcados
E I G E N V A L U E N U M B E R N — os vetores reutilizam o formato de linha
displacements (vx,vy,vz) estático, então as formas de modo são exportadas sem tocar
no .frd.
read_results_tool(result_path=...) # -> frequencies: [{mode, eigenvalue,
# freq_rad_s, freq_hz}], n_modes
export_results_tool(path="examples/cantilever_modal.inp", mode=1)
# -> result_mesh.json holding mode 1's eigenvector (stress-free shape)
Duas notas de física que valem a pena relatar honestamente: uma seção duplamente simétrica dá
pares degenerados (f1 = f2), e hexágonos C3D8 totalmente integrados travam por cisalhamento em
flexão, então as frequências ficam ~5-10% acima do cálculo manual de Euler-Bernoulli
(examples/cantilever_modal.inp: ccx f1 ~ 502 Hz vs cálculo manual ~ 464 Hz).
Instalação
A partir deste diretório (Linux/macOS; adapte a ativação do venv no Windows):
uv venv .venv --python 3.11
uv pip install --python .venv/bin/python "mcp>=1.0,<1.8" meshio numpy "python-dotenv>=1,<2"
uv pip install --python .venv/bin/python pytest # dev only
mcpestá fixado abaixo de 1.8:mcp2.0 removeumcp.server.fastmcp(a importação do FastMCP usada aqui e pelos outros MCPs do hub).
Instale o CalculiX separadamente (por exemplo, ccx ou ccx_preCICE no seu PATH, ou defina
CCX_EXE). fea_health informará se o executável foi detectado.
Execução
.venv/bin/python mcp_server.py # stdio MCP transport
Registre-o com um cliente MCP usando examples/mcp_config.example.json.
Exemplo: benchmark de viga em balanço
examples/cantilever.inp é uma viga em balanço pública de livro-texto (barra sólida C3D8 de aço,
fixada em uma extremidade, carregada transversalmente na outra). Regere-o com:
python3 examples/gen_cantilever.py
Metas de sanidade por cálculo manual (Euler-Bernoulli, mm-t-s-MPa, P = 100 N): deflexão da ponta ≈ 0,8 mm, tensão na raiz ≈ 140 MPa. O visualizador amplia automaticamente a pequena deformação elástica para exibição.
examples/cantilever_modal.inp é a mesma barra com uma etapa *FREQUENCY de 5 modos:
f1 = f2 ≈ 502 Hz (par degenerado), f3 = f4 ≈ 3089 Hz, f5 ≈ 6309 Hz,
vs o cálculo manual f1 ≈ 464 Hz (travamento por cisalhamento C3D8). O caso do visualizador
models/text-to-cae-calculix-modal renderiza o modo 1.
examples/plate_modal.inp (regere com
python3 examples/gen_plate_modal.py) é uma placa em balanço de casca S4 construída
para dimensionamento com restrição de frequência: ccx f1 = 37,6 Hz em t = 4 mm vs o
cálculo manual de Euler-Bernoulli f1 = (1,8751²/2π)(t/L²)√(E/12ρ) ≈ 37,1 Hz, e a
execução de evitar ressonância acima termina em t = 3,23 mm contra o ótimo analítico
t* = 30/9,29 ≈ 3,23 mm.
Testes
.venv/bin/python -m pytest
Testes de analisador e exportador rodam sem solver. Testes de solver são pulados
automaticamente quando ccx não é detectado, então a suíte permanece verde antes
da instalação do CalculiX.
Conteúdo
mcp_server.py— servidor stdio FastMCP.tools/inp_parser.py— análise de cartões.inp+ edição de texto no local.tools/solver.py— subprocessoccx+ análise de resultados.dat.tools/result_exporter.py—.dat/.inp→result_mesh.json(formato do visualizador).tools/optimizer.py— otimização de dimensionamento em dois estágios (LHS + descida de coordenadas).examples/— benchmark público de viga em balanço + gerador + exemplo de configuração MCP.tests/— suíte pytest.
Regras do repositório
Confirme apenas código-fonte reutilizável, exemplos (benchmarks públicos), testes e documentação. Não
confirme o ambiente virtual, .env ou qualquer saída de solver gerada
(.frd, .dat, .sta, .cvg, diretórios de job). Decks de entrada .inp são código-fonte
e são confirmados.