AmesimKnowledge

Community Knowledge > Headless Automation (AMEOpen)

Two engineering traps: AMEOpen on one thread, native modules imported on the main thread

Both cost about an hour on 2026-09-03 while wiring the AMEOpen API into the amesim MCP server (FastMCP) on Simcenter Amesim 2511. Both present as a silent hang, not an error, which is why they are written down.

Trap 1: the Qt-backed AMEOpen API must run on one thread

AMEOpen is Qt-backed. FastMCP dispatches tool calls from a thread pool, so two consecutive calls can land on two different threads. Calling the API from a thread other than the one that initialised it hung with no exception and no log line.

Fix in amesim_open.py: every AMEOpen call is marshalled onto one dedicated worker thread that owns the API instance for the life of the process. Tool handlers submit work to it and wait.

ame_apy does not have this constraint: it is thread-agnostic and can be called from whichever thread the server hands it.

Trap 2: import native modules on the main thread, before any worker use

With the worker thread in place, the first call still hung. A faulthandler dump of all thread stacks showed the worker sitting in create_module inside numpy's extension import: a deadlock on the Windows loader lock, triggered by importing a native extension for the first time on a non-main thread while the main thread held the lock.

Fix: numpy, matplotlib, the AMEOpen module and ame_apy are all imported on the main thread at server startup, before the worker thread exists. Worker code then only uses modules that are already loaded.

Two diagnostics that made this findable:

  • AMESIM_MCP_DUMP_AFTER=<seconds> in run_bridge.py dumps every thread's stack after the delay. That is what showed create_module in numpy.
  • A probe script that does not drain the server's stderr can itself look like a hang. Drain it before concluding the server is stuck.

The rule

Initialise the Qt-backed API once, on one thread, and keep it there. Import every native module on the main thread first. Neither rule applies to ame_apy, but nothing is lost by following them for it too.

Source: amesim-mcp/README.md (AMEOpen tools) and amesim_open.py, commit c287c02 · retrieved 2026-09-03