msforge
Generates editable NI Multisim 14 circuit files from plain-text netlists and layouts, performs offline connectivity and layout checks, reads existing designs, runs real DC operating point, AC sweep, and transient simulations through Multisim, and captures schematic previews and instrument-panel screenshots.
This server does not currently have a deployable release on Glama. Follow the repository's setup instructions to install and configure it for your MCP client, including any required credentials and local dependencies.
MultisimForge
Generate editable NI Multisim 14 circuits from plain text, verify connectivity offline, pull numbers out of Multisim's own simulation engine, and capture real instrument panels.
CLI + MCP server + agent skill in one package.
spec.json ──► MultisimForge build ──► .ms14 (editable) ──► MultisimForge check offline connectivity check
│
├──► MultisimForge preview real schematic PNG from Multisim
├──► MultisimForge sim real OP / AC / TRAN data
└──► MultisimForge capture real scope / bode panel screenshotsWhy
Multisim exposes no public "place a part, draw a wire" API — only a COM automation interface that has to run inside a 32-bit process. Doing a batch of circuits, or producing reproducible simulation data, means clicking through the GUI by hand.
MultisimForge treats a .ms14 file as an XML container: it implements the container codec itself, reconstructs the pin-to-net relationships from the drawing geometry itself, and routes wires itself. So you can generate and validate a circuit without Multisim running at all. Multisim is only started when real-machine behaviour is needed (schematic image, simulation numbers, instrument screenshots) — and a background worker keeps one instance alive so repeated calls reuse it.
Related MCP server: root-ext-cad
Features
Generate circuits: SPICE-style netlist plus part coordinates/angles →
.ms14. Automatic routing (obstacle-aware orthogonal A*, tree connection), multiple ground symbols, instrument panel presets, interactive simulation stop time.Explicit wiring: parts accept
mirror-x/mirror-y;wireslets you pin the exact polyline of any net (junctions are created automatically), andcolors/wire_widthcontrol wire colour and thickness.Offline self-check: reconstructs pin groups from wire and junction geometry and compares them against the electrical nets; also reports overlapping parts, wires crossing parts, crossings between different nets, and parts outside the sheet. No Multisim involved, so it cannot crash.
Any part: part templates are harvested whole from a
.ms14(electrical part + ports + model + symbol + panel state). Simulation uses the part's own model.Real simulation data: injects voltage probes on the nets you ask for, then drives DC operating point, AC sweep and transient analysis through COM — resonance peak, −3 dB frequency, phase, peak-to-peak, period. Arbitrary SPICE text can also be handed to Multisim's command-line engine.
Real screenshots: opens Multisim, runs the simulation, waits for the waveform to settle, then grabs the circuit window, each instrument panel and the full screen. If the scope trace does not fill the screen, the simulation time is recalibrated and the run repeats.
Reused COM instance:
preview/sim/parts fetchshare one hidden Multisim inside a background 32-bit worker — roughly 0.3 s for the second call, with no repeated launch/kill cycle.multisimforge com status/com stopinspect and release it.Read existing designs:
inspectreports parts, nets and instrument settings..ms14codec in pure Python: decoded XML matches the vendor decoder, and the XML layer round-trips byte for byte.
Requirements
Windows 10/11
NI Multisim 14.x (licensed)
Python 3.10+
pywin32,Pillow,numpy,scipyfor screenshotsa 32-bit Python with
pywin32— Multisim's automation interface is an in-process 32-bit componentoptional: Node.js +
electronics-workbench-decoder(onlyparts dbindexneeds it)
Local paths are detected at runtime (registry + install directories). Override them with a config.json in the repo root or with MULTISIMFORGE_<KEY> environment variables.
Install
git clone <this repo>
cd MultisimForge
python -m pip install -e .[capture]
MultisimForge parts init # build the part library from the local Multisim samples (~30 s)parts init harvests part templates from the samples shipped with your Multisim install and writes them to %LOCALAPPDATA%\multisimforge\parts. That directory is machine-local and is not distributed.
Quick start
examples/rc_lowpass.json:
{
"netlist": "V1 vin 0 DC 0 AC 1 SIN(0 1 1k)\nR1 vin vout 1k\nC1 vout 0 0.1u\nXSC1 vin vout 0 nc1 0 nc2 OSCILLOSCOPE\n",
"output": "out/rc.ms14",
"layout": {"V1": [108, 216], "R1": [252, 180], "C1": [396, 252, 90], "XSC1": [540, 126],
"GND": [[108, 306], [396, 342], [612, 198]]},
"instruments": {"XSC1": {"timebase": "500us", "a_scale": "1V", "b_scale": "1V", "trigger": "none"}},
"sim_time": "5ms"
}MultisimForge build examples/rc_lowpass.json --preview out/rc.png # generate + self-check + preview
MultisimForge sim out/rc.ms14 --ac 10,100k --out vout --in vin # cutoff frequency, phase
MultisimForge capture out/rc.ms14 shots # real screenshots (do not touch mouse/keyboard)capture works on a copy under work/capture/<run_id>/ and opens its own window,
so the input .ms14 is byte-identical before and after. A window title carries only
the file stem, so close any other window showing the same file name first: capture
refuses to guess which file such a window holds.
Every command prints one JSON envelope with a status and the matching exit_code:
{"problems": [], "warnings": [], "crossings": 0, "nets": {"vin": ["R1.1", "V1.1", "XSC1.1"]},
"status": "PASS", "exit_code": 0}status | exit code | meaning |
| 0 | every mandatory check passed |
| 0 | usable, with a declared caveat (layout advice, degraded routing you allowed) |
| 2 | the design is wrong: |
| 1 | the tool or the environment failed |
| 130 | interrupted |
A non-empty problems means the drawing disagrees with the netlist and must be fixed; warnings are layout advice (too many crossings, detours).
Routing
The router looks for a clean path before it reports a problem. It retries the pin escape at growing clearances, falls back to a denser A* grid, and routes the design up to three times with the failing nets moved first (rip-up and retry).
If a net still has no obstacle-free path, build tries to repair the layout:
it moves one part or one ground symbol by half a grid step (up to 48 tries, 3 s)
and keeps the cleanest result. The move is reported, so the run is WARN:
{"status": "WARN", "moved_parts": {"GND[1]": [0, 24]},
"warnings": ["layout auto-repaired: moved GND[1] by (+0,+24) so the router could pass"]}If no arrangement routes cleanly, build fails with RouteError and writes
nothing — it will not quietly draw a wire through a component. Two escape hatches:
MultisimForge build design.json --no-auto-repair # fail on the spec exactly as written
MultisimForge build design.json --allow-fallback # status WARN, degraded: trueExplicit wiring
The third element of a layout entry may be "mirror-x" / "mirror-y"; mirroring reverses pin order while labels stay horizontal:
"layout": {"XFG3": [45, 90, "mirror-x"], "XSC3": [183, 108], "GND": [[147, 171]]},
"wires": {
"out": [[[63, 90], [63, 144], [135, 144], [135, 126]]],
"0": [[[27, 90], [27, 171], [144, 171]], [[144, 126], [144, 171]]]
},
"colors": {"out": "red", "0": "red"},
"wire_width": 2Every segment must be horizontal or vertical, and polyline endpoints must land on a pin centre or coincide with another polyline (a junction is created at shared points). A net with wires follows those polylines exactly; other nets keep using the router. See examples/explicit_wiring.json.
Commands
Command | Purpose |
| search the part library (name, family, pin order) |
| pin order, hidden power pins, pin offsets and directions at 0° |
| pull a model out of the Multisim database when it is not in the library |
| harvest parts from existing |
| rebuild the whole part library |
| generate + self-check (optionally export a preview) |
| export the schematic through Multisim |
| offline self-check |
| report parts, nets, instrument settings |
| real simulation data |
| hand SPICE text to Multisim's engine |
| real screenshots: circuit, each instrument panel, full screen (needs no other window open for that file name) |
| change the interactive simulation stop time |
| inspect or release the background COM worker |
|
|
Flags
Command | Flag | Meaning |
|
| export a preview image after building |
| accept degraded wiring: status | |
| fail on the spec exactly as written; do not move parts | |
| — | reads a |
|
| nets to probe (required for meaningful data) |
| analyses to run (any combination) | |
| AC output node / AC input source | |
| time points to sample from a transient run | |
| also write each analysis to CSV | |
|
| SPICE command handed to Multisim's engine |
|
| how long the display must be still to call it finished (default 1.5) |
| maximum wait (default 90) | |
| leave the window open after capture | |
| continue past the netlist-error dialog (default: abort) | |
any |
| show the traceback instead of a JSON envelope on an unexpected error |
Durations must be greater than 0 and at most 3600 seconds.
MCP server
mcp_adapter/server.py is a stdio MCP server exposing the CLI as tools (check_design, inspect_design, build_schematic, capture_instruments, simulate, preview_design, set_sim_time, convert_design, parts, run_cli).
It is deliberately a thin, process-isolated shell: every tool shells out to python -m multisimforge <cmd> and returns the JSON the CLI prints. No Multisim COM object ever lives in the server process, so a COM crash or a failed screenshot run cannot take the server down.
python -m pip install -e .[mcp]
python mcp_adapter/server.py # stdio; let your MCP client launch itmcp_adapter/harness.py is an offline debug client: hand it a JSON call list, it launches the server, runs the calls and writes the results to JSON.
Layout
MultisimForge/
codec.py .ms14 container codec (PKWare DCL implode/explode, pure Python)
xmlio.py XML read/write (attribute newlines preserved, &ASC encoding, ID remapping)
parts.py part template library: harvest, index, lookup
structural.py extract structural templates from a blank design (shell, wire, junction, probe, sim state)
netlist.py netlist parser
builder.py spec → .ms14 (placement, rotation/mirror, labels, routing, instrument state, sheet size)
router.py pin escape + obstacle-aware orthogonal A* + tree connection
check.py offline self-check: geometry → electrical nets, plus layout checks
sim.py real simulation (probe injection, OP/AC/TRAN, result statistics)
capture.py real screenshots (PrintWindow, F5/F7 key posting, waveform coverage)
com.py COM worker (one reused Multisim instance)
config.py local path detection
mcp_adapter/ stdio MCP server + debug client
tools/dbindex.js read the Multisim master component database index (optional)Tests
python -m pip install -e .[dev]
python -m pytest -qThe offline suite covers the container codec, XML round-trips, the netlist parser, generation and connectivity of the three examples, and argument validation for mirroring and explicit wiring. CI runs on Windows and Linux (Linux runs only the parts that do not need Multisim).
Known limitations
Scope and bode cursors cannot be preset. The design file does carry the cursor positions (
NI_EWB_CURRENTDISPLAYDATA_CURSORPOS_0/1), and they survive a save, but Multisim 14.3 ignores the stored value when it opens the design: a file written with T1 = 1.5 ms, T2 = 3 ms opens with both cursors at 0 s, and requesting a restore throughNI_EWB_HASSERIALIZERESTOREDATAchanges nothing. Take readings fromsim, which asks the simulator instead of the screen.Multi-section parts (LM324, 74LS00, ...) use only section A per instance, and digital parts keep VCC/GND on hidden pins. The generator writes one symbol per instance.
Routing is automatic A,* so dense circuits can still detour — move coordinates or switch to
wires; thecrossingscount is the metric to optimise. When a layout has no legal route at all, the build fails and names the nets rather than shipping a drawing with wires through parts. Overlapping parts are the usual cause, and the only fix is to move a part, so auto-repair reports every move it makes.parts fetchcan crash Multisim. ReplaceComponent occasionally corrupts the process heap (0xC0000374) and Multisim exits. It depends on the state of the running instance rather than on the carrier circuit — the same fetch failed twice and then succeeded three times in a row after the instance was restarted. A crash now restarts the COM instance and retries once before reporting.capturetakes the foreground for the desktop screenshot. The circuit and panel images come fromPrintWindowand work with Multisim covered, but the full-screen image composites the real desktop, so it needs Multisim on top: leave the mouse and keyboard alone for about a minute. If the foreground cannot be taken, that one image is skipped with a warning and the others are still written.
License
MIT, see LICENSE. Third-party components and notices are listed in THIRD_PARTY_NOTICES.md.
This server cannot be deployed
Maintenance
Related MCP Connectors
QuLab MCP remote server (Streamable HTTP) for computational science and lab tools.
Headless CAD engine & MCP server for 2D/3D drafting, solids, DXF/SVG export, and automation.
MCP server for StyleKit styles, tokens, recipes, lint and repair over stdio or HTTP.
MCP server for progressive tool usage at any scale (see https://klavis.ai)
Related MCP Servers
- AlicenseBqualityDmaintenanceProduction-ready TypeScript MCP server exposing utility, GitHub, and Microsoft Teams tools over stdio.141MIT
- 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-
- AlicenseNot gradedqualityDmaintenanceA local MCP server for working with Logisim-evolution .circ projects, providing structured project inspection, guarded edits, validation, circuit analysis, test execution, format conversion, and GUI launch.2MIT
- AlicenseNot gradedqualityCmaintenanceEnables turning any command-line tool into an MCP server with auto-generated JSON schema, supporting stdio, timeouts, and stderr capture.MIT