← Discover MCPs and Agents
a
AgentOtherGitHub

acp-mcp-agent

MCP server for ACP(Pre) -lay-up read/edit, rule checks and export, headless via PyACP or live in the GUI.

Links

README

From the repo.

acp-mcp-agent

License: Apache 2.0 Python 3.10+ Platform: Windows ANSYS 2026 R1

Overview

An MCP server that lets an LLM agent drive ANSYS Composite Pre [ACP(Pre)] — read a lay-up, change fibre angles and layer counts, check manufacturing rules, and export the analysis model and composite definitions.

It talks to ACP two ways, and the difference matters:

agent ─┬─ acp_*      ──► PyACP ──► acp_grpcserver.exe   headless, batch / optimisation
       └─ acp_gui_*  ──► TCP 47800 ──► ACP-Pre GUI      live, visible on screen

PyACP launches its own headless ACP session and cannot attach to a running ACP-Pre window. So a second path exists: a small socket listener running inside the GUI's embedded Python, which executes model edits on the wx main thread. Angles change and the viewport redraws while you watch.

The two sessions are independent. acp_gui_* edits the model open in the GUI; acp_* edits the headless one. Pick one per task and stay there.

Scope is the upstream half of the composites loop. Solve and post-processing stay where they already work:

acp-mcp-agent (lay-up) ──► analysis model ──► Mechanical (BC / mesh / solve)
                       ──► composite defs ──► PyDPF-Composites

Live Demo

MCP ACP Alper — demo

Requirements

ANSYSwith ACP. Developed and tested with 2026 R1 (AWP_ROOT261)
Python3.10+ for the server side — whichever interpreter your MCP client launches
Packagesmcp, pydantic, ansys-acp-core (see requirements.txt)
OSWindows. The bridge itself is portable, the documented paths are not
ClientAny MCP client. Verified with Claude Desktop

ANSYS is not a pip package. ansys-acp-core starts the ACP gRPC server from a local ANSYS installation; without one, nothing here runs.

The GUI bridge needs nothing installed: it runs inside ACP-Pre's own embedded Python (3.10 on tested-2026 R1) and uses only the standard library plus wx, which ACP-Pre already provides.

Paths

Nothing in this repository has a machine-specific path compiled into it. One environment variable carries the location:

VariableRead byMeaning
ACP_BRIDGE_PATHacp_mcp.py, install_autoload.py, acp_gui_autoload.pyfull path to acp_gui_bridge.py
ACP_PROBE_OUT00_probe_pyacp.py, gui_probe.pywhere to write probe output (default: next to 00_probe_pyacp.py, temp dir for the GUI probe)
ACP_PROBE2_OUTgui_probe2.pywhere to write probe output (default: temp dir)

install_autoload.py bakes the resolved path into the model it installs into, so the embedded copy needs no environment variable afterwards.


Repository layout

acp_mcp.py              the MCP server - 15 tools, stdio transport
acp_gui_bridge.py       socket listener that runs INSIDE ACP-Pre
acp_gui_autoload.py     tiny loader, embedded in a model for a persistent bridge
install_autoload.py     embeds the loader in the open model, one call
mcp_config.example.json client registration template
requirements.txt
probes/
  00_probe_pyacp.py     stage 1: what this PyACP install actually exposes
  gui_probe.py          GUI console API exploration
  gui_probe2.py         deeper GUI console API dump
docs/
  pyacp_api_report.txt  reference probe output (yours lands in probes/)
  gui_probe2_out.txt    reference GUI console dump, 2026 R1
  acp-scripting-notes.md   undocumented ACP behaviour worth knowing

Setup from zero

1. Install the Python side

git clone https://github.com/aalperakiss/acp-mcp-agent.git
cd acp-mcp-agent
pip install -r requirements.txt

Delivered as a zip rather than a repository? Unpack it anywhere, cd into the folder and run the pip install line - nothing here depends on git, and the paths in this README are all relative to the folder root.

Use one interpreter and remember its absolute path — venv, Anaconda, whatever — but it must be the exact interpreter you put in the client config. A server that "cannot find mcp" is almost always a second Python.

2. Probe your ANSYS installation

python probes\00_probe_pyacp.py

Session probe only: if launch_acp() fails here, nothing downstream matters. The report lands in probes\pyacp_api_report.txt; docs\pyacp_api_report.txt is the reference from the development machine, kept for comparison. Then point it at a model:

python probes\00_probe_pyacp.py C:/path/to/your.acph5

PyACP renamed several methods between releases, so acp_mcp.py resolves each operation at call time from the CANDIDATES dict near the top of the file. Compare the probe report against CANDIDATES, PLY_ANGLE_ATTRS and PLY_COUNT_ATTRS, and add any missing real names — one place, one edit.

Need an .acph5? Open ACP-Pre and File → Save As. Having ACP-Pre open does not help PyACP by itself.

3. Register the server with your client

Claude Desktop config lives at %APPDATA%\Claude\claude_desktop_config.json. Paste the acp entry from mcp_config.example.json inside the existing mcpServers object, alongside whatever is already there. Do not replace the file. Watch the commas, and double every backslash (or use forward slashes).

Then quit the client completely — system tray included — and reopen. The tool list is fixed at startup; a running client will never see a new server.

Sanity check without a client:

npx @modelcontextprotocol/inspector python acp_mcp.py

4. Verify the headless half

Call in order, confirming each returns JSON rather than Error:

  1. acp_import_model
  2. acp_get_layup
  3. acp_set_ply_angles — change one ply, then re-read the lay-up
  4. acp_check_layup_rules — violations on a real model are normal
  5. acp_update_and_export
  6. acp_save_for_gui — open the result in ACP-Pre and eyeball it

That is already useful work: open a model, list the lay-up, change angles, check rules, export. Worth living with for a while before automating further.

5. Start the live GUI bridge

Open ACP-Pre with a model, open the Python console, and paste one line:

exec(open('<repo>/acp_gui_bridge.py').read())

You should see:

[acp_gui_bridge] listening on 127.0.0.1:47800

Now acp_gui_status from the agent returns pong: true and the name of the open model. From there acp_gui_set_ply_angles redraws the viewport live.

The listener lives in the ACP-Pre process. Close ACP-Pre and it is gone — paste the line again, or make it persistent as below.

6. Persistent bridge (optional)

Embed the autoloader in the model as a Script object, so ACP-Pre starts the listener on its own. In the ACP-Pre console:

import os
os.environ['ACP_BRIDGE_PATH'] = '<repo>/acp_gui_bridge.py'
exec(open('<repo>/install_autoload.py').read())

Then save the model. Three things make this safe rather than reckless:

  • The loader is embedded, the bridge is not. A Script object stores source as a string, so embedding the whole bridge would ship a listener to every machine that opens the file. The loader reads the bridge from disk instead; no file, no listener, one printed line.
  • It is idempotent. always mode fires on every model.update(), including the update the bridge itself triggers after a ply edit. The guard on sys._acp_bridge stops it rebinding port 47800 mid-request.
  • It fetches db itself. Script objects run with empty globals — no db, no model. The loader reaches the console namespace through __main__.

Scripts run on model update, not on file open, so install_autoload.py triggers one update to bring the listener up immediately. To remove it later, set model.scripts['acp_agent_bridge'].active = False and save.

Still keep a separate agent-enabled copy of shared models. A Script object is invisible in a design review, and a colleague opening your .acph5 should not inherit a socket listener by accident.


Tools

Headless (PyACP)

ToolDoes
acp_import_modellaunch a headless session and load a model
acp_get_layupplies in stacking order: angle, layers, material
acp_set_ply_anglesset fibre orientations, optional snap to manufacturable set
acp_set_ply_countsset layer counts; 0 deactivates a ply
acp_check_layup_rulessymmetry, balance, ±45 outer, ≤4 consecutive, direction fractions
acp_update_and_exportupdate, write analysis model and composite definitions
acp_save_for_guiwrite an .acph5 to inspect in ACP-Pre

Design vector first, export once: the set_* tools do not update or export.

Live GUI (socket bridge)

ToolDoes
acp_gui_statusis the bridge reachable, which model is open
acp_gui_get_layupread the lay-up from the GUI's model
acp_gui_set_ply_anglesset angles, redraw immediately
acp_gui_set_ply_countsset layer counts, redraw immediately
acp_gui_add_plyappend new modeling plies, inheriting material and OSS
acp_gui_savesave the GUI's model
acp_gui_exportexport analysis model / composite definitions from the GUI
acp_gui_execarbitrary Python in the live session, db and model in scope

Prefer the typed tools over acp_gui_exec for routine edits; the free-form tool is for exploration and one-offs.

acp_gui_add_ply takes a list of angles and appends one ply per entry, in stacking order. Material and oriented selection set are inherited from an existing ply (the last one in the group by default, or copy_from), because create_modeling_ply needs object references an agent cannot hold. A group with no plies at all therefore cannot be seeded from here - create the first ply in ACP-Pre.

Angles snap to 0, ±15, ±30, ±45, ±60, 90 by default. Turn snapping off explicitly when you want intermediate orientations.


Troubleshooting

SymptomCause
New tools missing after editing the configClient not fully restarted. Tool list is fixed at startup
Cannot reach the live ACP-Pre bridgeACP-Pre closed, or the bridge was never loaded in this process
Bridge call times out after 300 sGUI busy — an open dialog blocks the main thread
No active modelACP-Pre is running with no model loaded
launch_acp() failsANSYS not found, or the wrong Python. Check the probe first
Port 47800 in useAn orphaned listener. sys._acp_bridge.stop() in the console

Known gaps

  • acp_check_layup_rules flattens everything into one stack. Multi-region parts need per-OSS grouping before this is trustworthy on real geometry.
  • Ply creation exists on the live GUI side only (acp_gui_add_ply). The headless acp_* tools still edit existing plies only, so a model driven through PyACP must be built with enough spare plies up front.
  • Mass is not reported by the export tool; the attribute path varies too much between releases to guess. Add it once your probe report shows the real one.
  • Verified against one ANSYS release only. The CANDIDATES mechanism exists because older and newer releases will differ.

Security note

The bridge listens on 127.0.0.1 only and has no authentication. acp_gui_exec executes arbitrary Python inside ACP-Pre. Anything able to reach that port on the machine has the same power. Do not bind it to 0.0.0.0, and do not run it on a shared session.


Contributing

Issues and pull requests are welcome, particularly probe reports from ANSYS releases other than 2026 R1 — that is the fastest way to fill in CANDIDATES. Attach the generated probes/pyacp_api_report.txt and state the release.

Contributions are accepted under the Apache License 2.0 (see section 5 of the license). No CLA.

License

Apache License 2.0 — see LICENSE and NOTICE.

ANSYS, ACP, Composite PrepPost, Mechanical and Workbench are trademarks of ANSYS, Inc. This project is an independent integration and is not affiliated with, endorsed by, or supported by ANSYS, Inc. No ANSYS software or documentation is redistributed here; a licensed local ANSYS installation is required.

Collected info

  • 7 stars
  • Language: Python
  • Source updated: 9/12/2026