Skip to main content
Glama
ltspice-mcp

ltspice-mcp

by ossenna-hq

Repository provenance: this public integration fork is based on upstream cognitohazard/ltspice-mcp tag v0.5.0 (commit 4dc456000e1a436ef37a585c23ab35954a8caf04e). The additions in this branch provide installation-independent deployment examples and documentation. No upstream server source has been modified.

ltspice-mcp

Work in progress. Core functionality is usable but expect rough edges and breaking changes.

An MCP server that connects LLM assistants (Claude, and any other MCP client) to real circuit simulation: LTspice and ngspice, plus direct editing of LTspice .asc schematics. Simulation results come back as structured numbers — cutoff frequencies, overshoot, phase margin, rise times, and per-device small-signal operating-point parameters (gm, gds, vth, …) read back by name — so the assistant can design, verify, and iterate on circuits in the same files you open in LTspice, without ever hand-parsing a rawfile. Built on spicelib.

Quick start

In Claude Code, install the plugin:

/plugin marketplace add cognitohazard/ltspice-mcp
/plugin install ltspice-mcp

You also need LTspice or ngspice on the host (auto-detected on Windows, Linux, and macOS; on WSL set the LTspice path explicitly — WSL notes). Circuit editing works with no simulator at all. uv is required; the server itself is fetched from PyPI on first use.

Manual install (any MCP client)

Install the server, then point your client at it:

uv tool install ltspice-mcp     # or: pip install ltspice-mcp / pipx install ltspice-mcp

Claude Code — one command (drop -s project to install it globally):

claude mcp add -s project ltspice -- ltspice-mcp

Other clients — Claude Desktop, Cursor, Windsurf, Gemini CLI, Continue, Cline, Zed and others — add this mcpServers stanza to the client's MCP config file (each client documents its own path):

{
  "mcpServers": {
    "ltspice": { "command": "ltspice-mcp", "args": [] }
  }
}

Python 3.11+ required. Verify with ltspice-mcp --help. The same server is also published under two alias names — circuit-mcp and ngspice-mcp — so uvx circuit-mcp / uvx ngspice-mcp are drop-in equivalents of uvx ltspice-mcp if one of those names is more discoverable for you.

Web clients (claude.ai, ChatGPT) need a stdio→HTTP bridge such as mcp-proxy — only expose this server on a network you fully control, since it writes files and spawns processes inside allowed_paths.

A Claude Desktop extension is also available: build the .mcpb in packaging/mcpb/ and drag it onto Claude Desktop for a one-click install with a native folder picker for your circuits directory. Like the plugin, it wraps the PyPI package and needs uv and a simulator on the host (it does not bundle LTspice or ngspice).

Related MCP server: ltspice-mcp

Using it

Once connected, you ask for circuit work in plain language. The assistant designs the circuit and decides what to measure; the server runs the simulator, parses the binary output, and hands back the numbers. It reports what the run produced, the simulator's own warnings included, and leaves the call on whether a result is good to you and the assistant.

"Bias this NMOS common-source stage into saturation at the target drain current and report gm/ID."

The assistant writes the netlist, solves the bias point on LTspice, and reads the device's operating point back by name — drain current, gm, gds, VDS against VDSAT to confirm it's in saturation, and the gm/ID that analog designers size to. If the bias is off, it nudges the gate reference or W/L and re-runs, a couple of seconds per pass.

Other requests that work the same way:

  • "What's the overshoot and settling time of this regulator's step response?" — runs a transient analysis and measures both from the waveform, plus rise time, ringing frequency, and the final value.

  • "Run a 200-run Monte Carlo with 5% resistors and tell me the output spread." — perturbs components per run, simulates the batch, and reports mean, sigma, and worst-case values per measurement.

  • "Sweep the load from 100 Ω to 10 kΩ and find where efficiency drops." — parameter sweep with per-run results.

  • "Characterize this NMOS: gm and gm/ID vs VGS." — writes a .dc Vgs deck with .save @m1[gm] @m1[id], runs it on ngspice, and returns the gm/ID table as one CSV (no .control block, no rawfile parsing).

  • "Find an N-channel power MOSFET for a low-side switch and measure the on-state drop." — searches the loaded libraries for a part (find_model), drops it into a pulsed-gate transient, and reads Vds(on) and load current back from the .meas results.

  • "Build this differential pair as a schematic I can open in LTspice." — places and wires the components into a real .asc, with orthogonal routing and pin-collision checks.

  • "Is this loop stable?" — AC analysis of the loop gain; reports phase and gain margin at every crossover, not just the first.

  • "What's the resonant frequency and Q of this series RLC?" — runs an AC sweep and reports each peak's center frequency, Q, and −3 dB bandwidth.

The warning rides with the number it affects. A simulator like ngspice can print "singular matrix" once, deep in a log you'd never open, then finish the run and write perfectly plausible numbers anyway — read them by hand and nothing looks off. Ask the server for one of those numbers and the buried line comes attached to it, in an observations field right next to the value, so the failure surfaces where you're already looking instead of where it's easy to scroll past.

Co-design on the same files

Everything operates on ordinary LTspice and SPICE files, so the work passes back and forth between you and the assistant instead of living inside a chat:

  • Sketch a schematic in LTspice, then hand it over: "what's the bias point?", "why doesn't the output move?", "add compensation and check the phase margin."

  • Or the reverse: the assistant designs and verifies the circuit and writes the .asc; you open it in LTspice, inspect it, and tweak by hand. Your manual edits are simply the file's new state — the assistant picks up from there on the next request.

  • Changes can flow either direction mid-design: adjust a value in the GUI and ask for re-verification, or have the assistant sweep a change you're considering before you commit to it.

What it does

Simulation and measurement. Runs LTspice or ngspice and parses the binary output directly. Measurements are computed server-side and returned as numbers: time-domain (rise/fall, overshoot, settling, delay, period/duty/jitter, RMS, THD), frequency-domain (filter cutoffs and roll-off, gain and phase at any frequency, stability margins, resonance peaks with Q, integrated noise), DC operating points, and .MEAS directive results including the ones that failed. Per-device small-signal operating-point parameters (gm, gds, vth, …) come back by name on both simulators — LTspice via an auto-added .options logopinfo block in the log, ngspice via .save @dev[param] traces. Read the set across a .dc sweep as a gm/ID table with export_waveform, or a single bias point with operating_point (address them as m1.gm / @m1[gm], no rawfile parsing).

Schematic and netlist editing. Creates and edits real LTspice .asc files — place components, wire pins, label nets — with validation before anything is written: wiring that would collide with a pin, overlap a junction, or run diagonally is refused, and every edit returns warnings about floating pins or dangling labels. A session's edits can be reverted. Plain netlists (.cir/.net) get the same operations at text level, plus a static validation pass that catches malformed cards before a simulation is spent.

Sweeps and Monte Carlo. Multi-dimensional parameter sweeps and Monte Carlo with per-component tolerances, .MODEL process variation, and Pelgrom W·L device mismatch. Per-measurement statistics are aggregated across runs, and any single run can be pulled out and analyzed like a standalone simulation.

Jobs and trust. Simulations run as cancellable jobs with timeouts and a concurrency cap; long runs return a job ID immediately and job state survives a server restart. Results report facts, not verdicts: a completed run carries the simulator's own warnings, measurements that produced nothing, and extreme node values as structured observations. Judging whether a result is trustworthy is left to the model reading it.

Supported simulators

Simulator

Status

LTspice

Primary. Windows native, WSL2 (Windows LTspice.exe via interop), Linux via Wine. Required for .asc schematic editing (needs .asy symbol libraries).

ngspice

First-class: simulate, parse, diagnose, analyze. Open-source path with no LTspice install.

QSPICE, Xyce

Supported but secondary.

Configuration

Works with defaults out of the box. To customize, copy ltspice-mcp.example.toml to ltspice-mcp.toml; any setting can be overridden with an LTSPICE_MCP_-prefixed environment variable, and --config PATH or LTSPICE_MCP_CONFIG picks the file. Key options:

[simulator]
default = "ltspice"      # ltspice, ngspice, qspice, xyce (null = auto-detect)
path = ""                # explicit executable path (required on WSL)
ngbehavior = "hsa"       # ngspice compat mode; unset = spicelib default, "hsa" fixes sectioned .lib corner select

[security]
allowed_paths = ["."]    # sandbox: only these directories are accessible

[simulation]
max_parallel = 4
timeout = 300.0          # seconds

[tools]
profile = "full"         # or "agentic"

[state]
persist_jobs = true

See src/ltspice_mcp/config.py for the full option list ([analysis], [schematic], [logging], ...).

On WSL, LTspice.exe runs via Windows interop (not Wine), and spicelib can't auto-detect it across the WSL boundary. Set the Windows-side path explicitly:

[simulator]
path = "/mnt/c/Program Files/ADI/LTspice/LTspice.exe"

Simulation output is automatically redirected to a Windows temp directory: LTspice's .MEAS results go through SQLite .db files that fail on UNC paths (\\wsl.localhost\...), and without the redirect measurement data silently disappears from the logs.

.asy symbol paths for .asc editing are auto-detected on Windows and WSL; override with [schematic] symbol_paths or LTSPICE_MCP_SYMBOL_PATHS.

Tool profiles

Profile

Tools

Use case

full (default)

49

Any MCP client, automation, non-agent LLMs

agentic

41

LLM agents with native file access (Read/Edit/Write)

The agentic profile drops netlist-editing wrappers and library session management — work a capable agent does through direct file edits — and keeps simulation lifecycle, binary .raw parsing, batch orchestration, and the .asc geometry tools. The skills/ directory (skills/ltspice/SKILL.md, skills/ngspice/SKILL.md) contains the domain knowledge that pairs with it: copy the relevant skill into your client's persistent-instructions location.

Where it runs. The server shells out to a local LTspice/ngspice and reads circuit files from disk, so it must run where the simulator and the files are. Two setups work: a local MCP host (Claude Desktop, Claude Code, Cursor, Gemini CLI, Codex, …) on your own machine, or a browser-based cloud agent whose sandbox can install ngspice and register the server (verified with Claude). LTspice is local-only (a Windows app); ngspice is open-source and works in either place. Consumer web chat with no sandbox has no simulator and no file access, so it can't run this server directly; bridge it to a machine you control (e.g. mcp-proxy) if you want that UI.

Under the hood: the tool-level loop

What the assistant actually does for "design a 1 kHz RC low-pass and verify it". It writes the netlist (R=1k, C=159.155n → fc = 1 kHz):

* rc.cir — RC low-pass
V1 in 0 AC 1
R1 in out 1k
C1 out 0 159.155n
.ac dec 50 1 1Meg
.end

then drives three tools:

validate_netlist(path="rc.cir")
  → OK: directives valid, element arities check out — safe to simulate

run_simulation(netlist="rc.cir")
  → {"job_id": "sim_a3f1", "status": "completed", "raw_file": ".../rc.raw", ...}

bode_metrics(raw_file=".../rc.raw", signal="V(out)", mode="filter")

and gets back scalars, not a plot:

{
  "signal": "V(out)",
  "filter_type": "lowpass",
  "passband_gain_db": 0.0,
  "passband_ripple_db": 0.02,
  "cutoff_low_hz": null,
  "cutoff_high_hz": 1000.4,
  "stopband_rejection_db": 59.97,
  "rolloff_slope_db_per_decade": -19.9,
  "estimated_order": 1,
  "warnings": []
}

(abridged — the full response also includes passband bounds and transition bandwidth)

Off-target → set_component_value, re-run, re-measure. Long simulations return a job ID instead of blocking; check_job/cancel_job manage them. Job metadata persists in per-circuit sidecars ({dir}/.ltspice-mcp/jobs/ — add .ltspice-mcp/ to your .gitignore), and MCP resources (spice://results/..., spice://netlists/..., spice://config) expose jobs, signals, measurements, and config for browsing.

Every tool declares MCP annotations (readOnlyHint, destructiveHint, idempotentHint, openWorldHint); data-returning tools declare an outputSchema for structuredContent introspection.

Tool

Description

create_netlist

Create a new netlist from a content string

create_schematic

Create an empty .asc ready for incremental editing

read_circuit

Read a circuit file (netlist text for .cir, schematic layout for .asc)

list_components

List components (optional prefix filter) or look up one by reference

set_component_value

Set one component value, or batch-set many via a values dict

parameter

Read all .PARAM values or set one

edit_directive

Add or remove SPICE directives (.tran, .ac, .lib, ...)

add_component

Add a component; returns pin positions, bounding box, overlap warnings

connect

Wire two pins by reference with waypoint routing; validates pin collisions, junctions, diagonals

symbol_info

Symbol pin positions, directions, bounding box, description

component_info

Placed component pin positions, bounding box, attributes

export_netlist

Export .asc to .net via LTspice (with diff against previous export)

validate_netlist

Static pre-flight checks on a netlist or schematic before simulation

trace_net

Every pin/label/wire on a net at a pin / net:NAME / (x,y); flags accidental shorts

reset_schematic

Revert an .asc to its pre-edit snapshot from this session

diff_circuit

Structural diff between two circuit files

apply_schematic_ops

Apply many .asc edits in one transaction; home for the ack-only mutation ops (move_component, remove_component, set_component_attribute, add_net_label, remove_net_label, remove_wire)

run_simulation

Run a simulation — sync for short runs, async (job ID) for long ones; sets batch flags, handles the ngspice headerless-raw dialect, routes raw/log artifacts, surfaces convergence/timeout errors (no hand-parsing a rawfile)

check_job

Check a job's status by ID, or list all jobs

cancel_job

Cancel a running simulation or batch; kills the simulator process(es)

signal_stats

Min, max, mean, RMS, peak-to-peak (dB/phase for AC)

get_waveform

Decimated min/max stat-envelope of a signal over a window — see the shape, then re-request a narrower window to zoom

export_waveform

Full-fidelity CSV egress of one or more signals to disk (all analysis types; tidy/long for .step); accepts device operating-point params (m1.gm/@m1[gm]) — across a .dc sweep this is the gm/ID-table read; returns the path to compute on yourself

plot_waveform

Interactive HTML chart (transient / DC / Bode dual-panel with ac_structure corner + non-minimum-phase markers / noise / .step overlay) written next to the circuit and opened in your browser; for seeing shape, not measuring

query_value

Signal value at a specific time/frequency (or a device operating-point param, m1.gm/@m1[gm]); step_axis+step_value picks a .step run

operating_point

DC operating point: all node voltages, branch currents, and per-device operating-point params (gm/gds/vth/…) on LTspice (auto .options logopinfo) and ngspice, addressable as m1.gm/@m1[gm]; device= scopes to one device

simulation_summary

Full summary: simulation type, signals, measurements, warnings

edge_metrics

Rise/fall time and slew rate for one transient edge

pulse_response

Overshoot, undershoot, settling time for a step response

timing_between

Propagation delay between two transient signals

periodic_metrics

Period, frequency, duty cycle, jitter of an oscillating signal

thd

Total harmonic distortion (THD/THD+N) of a periodic transient via FFT; coherent sampling for an exact result; surfaces every condition

measurement_stats

Aggregate .MEAS scalars across a sweep or Monte Carlo run

bode_metrics

AC/Bode analysis by mode: filter, slope, point, crossing; all_steps=true for per-step results

stability_metrics

Loop-gain stability: all unity-gain / -180° crossings with per-crossing margins

resonance

AC peaks with Q factor and -3 dB bandwidth per peak

ac_structure

Pole/zero structure of an AC response: net order, corner ranges + Q, non-minimum-phase / RHP-zero, transport delay (facts for human review)

noise_integral

Integrate a .noise spectral density to total RMS over a band (sqrt(∫ density² df)); reports the band and sample count

configure_sweep

Configure a multi-parameter sweep (linear or log)

run_sweep

Execute a configured sweep (async, returns job ID)

configure_montecarlo

Configure Monte Carlo: tolerances, .MODEL variation, Pelgrom mismatch

run_montecarlo

Execute a configured Monte Carlo analysis (async, returns job ID)

batch_results

Sweep/MC job progress, per-signal statistics, or per-run data

find_model

Find model candidates by name (fuzzy by default, exact=true for exact)

load_library

Load a .lib/.mod file or a directory of libraries

unload_library

Unload a previously loaded library

list_libraries

List loaded libraries, optionally with model names

server_status

Detected simulators, config, sandbox paths, runtime state

recent

Recently-used circuits and jobs from the persistent index

Development

uv sync                        # install runtime + dev dependencies
uv run pytest tests/ -v        # tests
uv run pyright                 # type checking
uv run ruff check src/ tests/  # lint
uv run ltspice-mcp             # run the server (stdio)

More: docs/DESIGN.md (scope, architecture, non-goals) and docs/spice_lex.md (SPICE parser internals).

License

GPL-3.0

Available Tools

49 tools
ac_structureA
Read-onlyIdempotent

Read the pole/zero STRUCTURE of an .AC response — net order, corner frequencies (as ranges) with Q, out-of-phase zeros, and transport delay — to support design reasoning (where the poles/zeros roughly are, damping, out-of-phase zeros). It first tries a rational fit and uses its poles/zeros when the fit is clean; otherwise it falls back to asymptotic Bode reading (slope breakpoints + joint gain-phase + group delay + a gain-phase consistency residual).

Returns FACTS, not a verdict — bring your own control/design knowledge. The most design-critical fact is the non_minimum_phase flag: an out-of-phase zero or a transport delay adds phase lag the magnitude plot cannot show, and caps achievable loop bandwidth; do not close a loop on magnitude alone when it is flagged.

IMPORTANT — these are read from a finite sweep, so HAVE A HUMAN REVIEW them against the Bode plot (use plot_waveform on the same signal) and the circuit before acting. Closely-spaced corners merge into one range (merged: true) rather than being resolved individually, and exact pole/zero COUNTS are not guaranteed — for exact poles/zeros run a .pz analysis on ngspice. Requires a .AC run. Siblings: bode_metrics (margins / cutoffs / point queries), resonance (peaks + Q), stability_metrics (loop margins).

Inputs: signal (required), step, format, job_id, +2 more. Returns: method, signal, corners, net_order, +7 more

add_componentA

Add a new component to an .asc schematic at a specified grid position.

Inputs: x (required), y (required), path (required), symbol (required), +5 more. Returns: pins, symbol, position, rotation, +3 more

apply_schematic_opsA
Destructive

Apply many .asc edits in one transaction. Loads the schematic once, runs each op against the in-memory editor in order, and saves once at the end. Cuts the typical 25+ tool calls to build a real circuit (add_component × N + connect × N + add_net_label × N + edit_directive × N) down to a single round-trip. This is also the home for the ack-only schematic mutations that have no standalone tool — they return no geometry to act on, so they live here rather than each costing a separate tool slot.

Supported ops (each tagged via the op field): add_component, set_component_value, set_component_attribute, remove_component, move_component, add_net_label, remove_net_label, remove_wire, connect, add_directive, remove_directive.

By default, the first op that raises aborts the whole transaction and nothing is written to disk. Set stop_on_error=false to run every op and persist whatever subset succeeded — useful when each op is independent and partial progress is acceptable. Errors are recorded under each op's error field; successes carry the per-op result keys (e.g. wire_count).

Inputs: ops (required), path (required), format, dry_run, +1 more. Returns: path, saved, dry_run, results, +3 more

batch_resultsA
Read-onlyIdempotent

Query a batch simulation job (sweep or Monte Carlo). Without signal: returns job status and progress. With signal: returns aggregate statistics or per-run data for that signal.

Inputs: job_id (required), at, raw, limit, +4 more. Returns: mode, runs, stats, job_id, +12 more

bode_metricsA
Read-onlyIdempotent

AC / Bode-plot analysis in one tool, selected by mode. The response shape depends on the mode: mode='filter' — filter type, cutoffs (at ref_db below passband), passband gain/ripple, stopband rejection, transition BW, pole-order, and an auto-estimated asymptotic roll-off slope (dB/decade) — covers cutoff AND slope in one call. mode='slope' — magnitude slope (dB/decade + dB/octave) between f_low and f_high; pick endpoints ≥1 decade past any knee. Use when you need a custom window or dB/octave ('filter' already reports an auto-estimated asymptotic dB/decade slope). mode='point' — magnitude (dB + linear) and phase at each of frequencies (log-axis interpolation; out-of-range clamps + warns). mode='crossing' — every frequency where quantity crosses level (phase is UNWRAPPED first); the escape hatch for custom queries like unity-gain (0 dB) or phase-margin (-180°) frequencies.

Pass all_steps=true to compute the chosen mode for every step of a .step sweep in one call (returns a steps list instead of a single result) — e.g. the -3 dB cutoff at every value of a stepped component.

To analyze a run of a completed sweep/MC job, pass job_id + run_index instead of raw_file (combine with all_steps to also sweep the .step axis within that run).

For loop-gain stability margins use stability_metrics; for resonant peaks & Q use resonance.

Inputs: mode (required), signal (required), step, f_end, +19 more. Returns: mode, level, steps, params, +31 more

cancel_jobA
DestructiveIdempotent

Cancel a running simulation job (single run, or a sweep/Monte-Carlo batch). Kills the simulator process(es) and marks the job as cancelled.

Inputs: job_id (required).

check_jobA
Read-onlyIdempotent

Check status of a simulation job by ID, or list all jobs. Without job_id: lists active jobs (filter with status param). With job_id: returns detailed status or completion results.

Inputs: format, job_id, status. Returns: jobs, count, error, range, +23 more

component_infoA
Read-onlyIdempotent

Get a placed component's pin positions, bounding box, value, and attributes from an .asc schematic.

Inputs: path (required), reference (required), format. Returns: pins, value, symbol, position, +4 more

configure_montecarloA
Idempotent

Configure a Monte Carlo analysis with component tolerances and return a config_id for later execution.

Inputs: netlist (required), seed, mismatch, num_runs, +3 more.

configure_sweepA
Idempotent

Configure a multi-parameter sweep for a netlist and return a config_id for later execution. Dimensions combine as a full cross-product, so this also covers deterministic worst-case corner analysis (give each component a two-value [low, high] set — N parts yields 2^N corners that bound the true extremes, which random Monte Carlo cannot guarantee) and sensitivity analysis (sweep one part at a time across its tolerance to rank impact). Use configure_montecarlo instead for statistical yield/spread. NOT for a bias sweep: a native .dc Vds Vgs (e.g. a gm/ID characterization) goes in one deck + run_simulation + export_waveform, not here — this is for per-value SEPARATE runs (corners, L/W, .lib model swaps).

Inputs: netlist (required), parameters (required).

connectA

Connect two component pins with wire(s). Resolves pin positions automatically. Waypoints define the wire route through intermediate points. For a straight horizontal or vertical connection, waypoints can be omitted.

Inputs: path (required), to_pin (required), from_pin (required), waypoints. Returns: to, from, points, warnings, +2 more

create_netlistA
Destructive

Create a new SPICE netlist file from content string. Automatically appends .END if missing.

Inputs: name (required), content (required), overwrite.

create_schematicA
Destructive

Create an empty .asc schematic ready for incremental editing via add_component / connect / add_net_label. Tip: prefer create_netlist + .cir for design iteration; use this only when a visual schematic is the deliverable. Prefer apply_schematic_ops for multi-step builds (one transaction); wire signal nets with connect; label grounds — and any net a .meas/B-source references by name — via add_net_label flags at pins. Don't hand-edit the .asc. Full layout guidance: the spice://guide resource.

Inputs: name (required), width, format, height, +1 more. Returns: path, width, height

diff_circuitA
Read-onlyIdempotent

Structural diff between two circuit files: reports added/removed components, components whose value or attributes (Value2/SpiceLine/SpiceModel) changed, and added/removed .PARAM/.MEAS/.MODEL directives. Use after set_component_value, set_component_attribute or edit_directive to confirm that the intended change actually landed.

Inputs: path_a (required), path_b (required), format.

edge_metricsA
Read-onlyIdempotent

Use when you need to quantify HOW FAST one transition happened: rise time, fall time, slew rate. Inputs a transient .raw plus a time window around the edge of interest.

Returns: transition_time (10→90% by default, configurable via low_pct/high_pct), slew_rate (V/s or A/s), detected low/high levels, and the three crossing times.

Levels are auto-estimated from the first/last 10% of the window — NOT global min/max — so overshoot/undershoot doesn't poison the level estimate. Crossings are sub-sample-accurate via linear interpolation. Rejects AC analysis.

PICK THE WINDOW. If the transient has startup glitches or multiple edges, set t_start/t_end tightly around the edge you care about — otherwise you get the first edge in the full waveform, which is often the power-up artifact. Use edge_index only when multiple edges in the window are intentional.

For settling/overshoot after the edge, use pulse_response. For delay between two signals' edges, use timing_between.

Inputs: signal (required), edge, step, t_end, +10 more. Returns: signal, low_pct, high_pct, warnings, +10 more

edit_directiveA

Add or remove a SPICE directive or .asc free-text comment. Set kind=comment for annotation text; default is a SPICE directive. Works on .cir/.net and .asc; kind=comment is .asc-only. remove matches against directives AND comments, so callers can delete either kind without knowing which it is. Adding a .param is not supported here — use the 'parameter' tool to set .PARAM values.

Inputs: path (required), action (required), instruction (required), x, +3 more.

export_netlistA
DestructiveIdempotent

Export an .asc schematic to a SPICE netlist (.net) using LTspice.

Inputs: path (required).

export_waveformA

Full-fidelity waveform egress: write every sample of one or more signals to a CSV file on disk and return its path — for when you want to compute on the raw data yourself (FFT, custom metrics, cross-correlation) rather than read a scalar or a decimated envelope.

Lossless within the chosen window (no decimation — that is get_waveform's job). Works on transient (.tran), DC sweep (.dc), AC (.ac), and noise (.noise). Complex AC traces are written as magnitude(dB)+phase(deg) by default (complex_format selects re/im or both); phase is the wrapped np.angle — run np.unwrap yourself for a continuous curve. A stepped (.step / Monte-Carlo) run is written tidy/long: one row per (step, sample) with leading step_index/step_value columns, because each transient step has its own time vector. The observations list surfaces FACTS (rows written, window coverage, non-finite samples KEPT, the complex format used) — not verdicts.

Returns the CSV path plus row/column counts; read the file with your own tools. Sibling egress, don't confuse: get_waveform returns a DECIMATED envelope as numbers in your context (no file); plot_waveform renders an interactive PICTURE for a human. For a single scalar use signal_stats/query_value.

Inputs: t_end, format, job_id, out_dir, +5 more. Returns: path, columns, n_steps, signals, +6 more

find_modelA
Read-onlyIdempotent

Find model/subcircuit candidates across loaded (and optionally built-in) libraries. Default is fuzzy matching — finds typos, case variants, and near-neighbour part numbers (e.g., '2N3905' → '2N3904'); pass exact=true to only return the exact case-insensitive match. Returns ranked candidates with similarity score and an include_directive emitted in the simulator's native path form (on WSL this is the Windows path LTspice.exe expects, not the /mnt/c Linux path). Each candidate carries ports (the .SUBCKT port list, empty for .MODEL) and params (default parameter values from the body / params: clause). For .MODEL devices it also carries device_type (the SPICE device token: NPN, PNP, D, NMOS, VDMOS, NJF …) and, for recognised tokens, a usage connection-order string (e.g. Qxxx C B E <name>) — a .MODEL gives parameters but not node order, and wiring the part in the wrong order simulates silently wrong.

Inputs: name (required), full, exact, limit, +3 more. Returns: exact, query, cutoff, results, +1 more

get_waveformA
Read-onlyIdempotent

Decimated numeric egress FOR THE MODEL: returns a min/max-preserving stat-envelope of one real-valued signal as DATA in your context (numbers, not a picture) over a time/sweep/frequency window — for when a scalar isn't enough and you need the SHAPE (switching nodes, amplifier internal nodes, startup transients).

Splits the window into equal-time buckets; each bucket reports the raw sample min/max (a narrow spike or ringing peak is never averaged away), time-weighted trapezoidal mean/rms (correct on SPICE's adaptive timestep), pk_pk, and crest_factor (peak/rms — high = impulsive/spiky). Scalar-guided zoom: read the envelope, then re-request a narrower [t_start, t_end] to resolve a region at higher resolution (same call, tighter window). The observations list surfaces FACTS, not verdicts (decimation coverage, dropped non-finite samples, which bucket has the largest pk-to-pk) — you decide what the shape means.

Works on transient (.tran), DC sweep (.dc), and noise (.noise) results. Sibling egress, don't confuse: export_waveform writes EVERY sample to a CSV FILE for your own code; plot_waveform renders an interactive PICTURE for a human to look at. For complex AC data use bode_metrics; for a single scalar use signal_stats; for one point value use query_value.

Inputs: signal (required), step, t_end, format, +5 more. Returns: signal, buckets, axis_unit, decimated, +7 more

list_componentsA
Read-onlyIdempotent

List components in a circuit file, optionally filtered by type prefix, or return a single component value by reference.

Inputs: path (required), limit, format, offset, +2 more. Returns: components, pagination

list_librariesD
Read-onlyIdempotent

List loaded libraries. With detail=true, also shows the .SUBCKT and .MODEL names defined in each library (so foundry .bjt/.mod files with hundreds of .MODEL cards are discoverable without guessing), and names encrypted vendor files whose bodies can't be parsed.

Inputs: path, limit, detail, format, +1 more. Returns: libraries, pagination

load_libraryA

Load a SPICE library file (.lib, .mod) or directory of library files into the session.

Inputs: path (required).

measurement_statsA
Read-onlyIdempotent

Use to AGGREGATE .MEAS scalar results across a .step sweep or Monte Carlo run. Answers questions like 'across 100 MC trials, what's the worst-case rise time?' or 'how does gain vary as R sweeps 1k..10k?'. Inputs the .log file produced by the run.

Returns per-measurement: min, max, mean, median, std, p10, p90, min_step_index (argmin) and max_step_index (argmax), failure count, and an optional histogram (set histogram_bins=0 to skip).

Accepts any job id: a sweep/MC batch aggregates across its runs; a single-simulation job aggregates its own log (one value per step for a .step run). WHEN-style .MEAS (constant level, varying crossing) is detected the same way on both paths and swaps to aggregating the 'at' (crossing) field; the aggregated_field output says which was used. On a plain single run, stats collapse to n=1 (one value per measurement): the headline stats are the value the simulator printed — for a WHEN that's the trigger level — and any AT/crossing time is returned separately in the entry's 'at' field, so a single-run WHEN/AT read isn't lost. (simulation_summary also just reads the raw scalars.)

Works with .MEAS from any analysis type (.tran/.ac/.dc/.op) — the measurement directives themselves embed the analysis context. Pass measurement=NAME to aggregate just one; otherwise returns all .MEAS in the log.

Inputs: format, job_id, log_file, measurement, +1 more. Returns: stats, per_run

noise_integralA
Read-onlyIdempotent

Integrate a .noise spectral density to a total RMS noise over a band. SPICE stores amplitude density (V/√Hz or A/√Hz) for both LTspice and ngspice, so total = sqrt(∫ density² df) — the same value LTspice shows when you Ctrl-click a V(onoise) label. Reports the band actually integrated and the sample count. Noise figure / SNR are left to you (they need the source resistance and a reference level).

Inputs: step, f_end, format, job_id, +4 more. Returns: unit, signal, n_points, warnings, +4 more

operating_pointA
Read-onlyIdempotent

Read DC operating point data: all node voltages, branch currents, and each semiconductor's small-signal params (gm/gds/vth/vdsat/caps) — from LTspice's log (run_simulation auto-adds '.options logopinfo' on .op runs) or ngspice's @dev[param] traces, surfaced uniformly by name. Each value carries its SI unit where the simulator declared the type (see units). Pass device='M1' to get just one device's params + terminal currents in a single call.

A run-level solve failure (singular matrix / non-convergence) taints every value here; that simulator line is relayed into warnings — read it before trusting the bias point.

Inputs: at, step, device, format, +3 more. Returns: step, units, device, currents, +5 more

parameterA
Idempotent

Read, write, or delete .PARAM directive values in a circuit file. Pass delete=true with name to remove a parameter (the inverse of setting one).

Inputs: path (required), name, value, delete, +1 more. Returns: parameters

periodic_metricsA
Read-onlyIdempotent

Use for an oscillating transient signal (clock, oscillator output, switching waveform) when you need period, frequency, duty cycle, pulse widths, and period-to-period jitter.

Returns: period (mean across measured periods), frequency (1/period), jitter_rms (std-dev of period lengths — timing jitter, NOT signal amplitude variance), duty_cycle_pct, mean high/low pulse widths, edge counts. duty_cycle_pct / pulse_widths are null if no full periods could be paired. A period is the span between consecutive rising crossings, so num_periods_measured = num_rising_edges - 1 (you need N+1 edges to measure N periods).

Uses threshold crossings; threshold defaults to the midpoint of window min/max. For a signal with DC drift, set an explicit threshold — the auto midpoint moves with the drift and the edge detection gets unstable. min_periods guards against accidentally running on 1-edge windows.

Skip the startup transient via t_start/t_end; the first cycle is often wider than steady state. Rejects AC analysis. For a single edge (not periodic), use edge_metrics.

Inputs: signal (required), step, t_end, format, +6 more. Returns: period, signal, warnings, frequency, +8 more

plot_waveformA

Render an INTERACTIVE chart of one or more signals FOR A HUMAN to look at (zoom/pan/hover) — the co-design complement to the numeric tools. It returns NO data values to the model; it produces a picture.

Picks the chart from the run type: transient (V/I vs time), DC sweep, AC Bode (stacked magnitude-dB + phase-deg vs log frequency), noise (vs log frequency); a .step / Monte-Carlo run overlays every step as a labelled trace (or pass step for one). Full fidelity by default, with a min/max-preserving downsample above max_points (spikes survive; surfaced as a fact). Writes a self-contained HTML file and returns its path — into out_dir if given, else a '.ltspice-mcp/plots/' sidecar next to the circuit (for a job_id) or next to the raw (for a raw_file); on a host that supports MCP Apps the chart is also embedded as an interactive in-chat widget, otherwise it opens in your local browser.

Sibling egress, don't confuse: for numbers in your context use get_waveform (decimated); for every sample on disk use export_waveform (CSV); for a scalar use signal_stats/bode_metrics. This tool is for looking, not measuring.

Inputs: open, step, t_end, format, +8 more. Returns: path, opened, opener, panels, +11 more

pulse_responseA
Read-onlyIdempotent

Use when you need step-response quality metrics: overshoot %, undershoot %, settling time, peak value and peak time. Inputs a transient .raw covering ONE step transition — ideally with the stimulus edge near t_start and enough tail to see settling.

Returns: direction (rising/falling), initial/steady-state values, peak (absolute and pct), settling_time (to within settling_tolerance_pct band). settling_time is null in three cases, kept distinct in the text and quality flags: 'never (within window)', 'undefined (full-pulse window)', and 'unknown' when the trailing window is too noisy to trust the final value (still ringing) — pass final_value there.

Definitions: overshoot is excursion BEYOND final in the step direction; undershoot is excursion beyond initial opposite the step direction. overshoot_pct = 0 means MEASURED overdamped, not missing data. settling_tolerance_pct defaults to 2% of |final - initial|; 1% and 5% are also common.

If the auto-detected initial/final (mean of first/last 10% of window) is contaminated by ringing, pass explicit initial_value/final_value. Rejects AC analysis.

For just rise/fall time without overshoot, use edge_metrics.

Inputs: signal (required), step, t_end, format, +7 more. Returns: signal, quality, warnings, direction, +8 more

query_valueA
Read-onlyIdempotent

Look up the value of a signal at a specific time point (transient) or frequency (AC). Returns the nearest data point without interpolation.

To pick a step of a .step/.DC sweep by its axis VALUE (rather than a raw step index), pass step_axis + step_value (e.g. step_axis='temp', step_value='27'); at then selects the inner-axis point within that step (optional). AC samples also return magnitude_linear alongside magnitude_db/phase_deg.

To query a run of a completed sweep/MC job, pass job_id + run_index instead of raw_file — the run is analyzed like any standalone raw.

This is one signal at one point (signal=). For many signals, or a whole waveform over a window, use export_waveform (signals=).

If the run hit a run-level solve failure (singular matrix / non-convergence), that simulator line is relayed into warnings — the value is still returned, but the whole solve is suspect, so read it.

Inputs: signal (required), at, step, format, +5 more. Returns: axis, unit, value, signal, +12 more

read_circuitA
Read-onlyIdempotent

Read and parse a circuit file (.cir/.net or .asc). For netlists: returns content and component values. For schematics: returns layout and directives.

Inputs: path (required), format. Returns: file, type, wires, labels, +4 more

recentA
Read-onlyIdempotent

Call on session start to find circuits the user was last working with, including jobs that were still running when the server stopped. Needs no inputs.

Returns a list of recent circuits, each with its absolute path, whether the file still exists, last-touched timestamp, total persisted job count, status_counts (completed/failed/interrupted/etc.), and the IDs of any interrupted jobs.

'interrupted' means a simulation was in flight when the server stopped — recovery path is check_job(job_id) to see whether results are recoverable or the run needs to be re-kicked. Does NOT start or cancel anything; purely read-only.

Inputs: format. Returns: count, circuits

reset_schematicA
DestructiveIdempotent

Revert an .asc schematic to the state it had BEFORE the first edit this session — a recovery escape hatch for when a sequence of edits went wrong. The server snapshots each .asc file's bytes just before its first in-session mutation (add_component, set_component_value, move_component, connect, apply_schematic_ops, etc.); this restores that snapshot exactly and drops it (so a later edit establishes a fresh restore point). Because add_component is a trigger, the first add_component on a freshly created schematic snapshots the empty file — so reset can revert all the way back to the empty post-create state, dropping every component added this session. Returns reverted=false (not an error) when the file has no recorded in-session edits. Note: the snapshot lives only for the current server session — it does not persist across restarts, and it is not a substitute for version control.

Inputs: path (required), format. Returns: path, bytes, reverted

resonanceA
Read-onlyIdempotent

Detect magnitude peaks in an AC sweep and estimate Q factor + -3 dB bandwidth for each. Useful for RLC resonators, crystal oscillators, peaking amps, or any response with distinct resonant modes.

Q = f_peak / Δf(-3 dB from peak). Q is returned as null for peaks without two flanking -3 dB crossings inside the swept range — widen the sweep if you need Q for a boundary peak.

min_prominence_db=3 rejects the gentle hump of a filter's passband (which isn't a resonance). Tight resonances (Q > 30) need dense sampling near f_peak — log sweeps with <50 pts/decade will under-sample the peak and give inflated Q/bandwidth.

For overall filter characterization use bode_metrics(mode='filter'); for stability margins use stability_metrics.

Inputs: signal (required), step, format, job_id, +5 more. Returns: peaks, signal, warnings, num_peaks_detected

run_montecarloA

Execute a previously configured Monte Carlo analysis asynchronously and return a job_id immediately.

Inputs: config_id (required), max_parallel.

run_simulationA

Run a SPICE simulation on a netlist file. Sets the right batch flags, handles the ngspice headerless-raw dialect, routes the raw/log artifacts, and parses the results — so you never hand-parse a rawfile. Automatically runs synchronously for short simulations (<=30s timeout) or asynchronously for longer ones. Use wait=true to force synchronous execution. Returns raw/log file paths and simulation summary on completion, or a job ID for async tracking.

Inputs: netlist (required), wait, format, timeout. Returns: error, range, errors, job_id, +16 more

run_sweepA

Execute a previously configured parameter sweep asynchronously and return a job_id immediately.

Inputs: config_id (required), max_parallel.

server_statusA
Read-onlyIdempotent

Get comprehensive server status including detected simulators, configuration settings, security sandbox paths, and runtime state. Use this to check what capabilities are available before attempting operations.

Inputs: format. Returns: runtime, simulators, tool_count, diagnostics, +6 more

set_component_valueA
Idempotent

Set component value(s) in a circuit file (single or batch mode), or rewrite one component's node connectivity ('nodes', single mode, .cir/.net only). A no-op value write is reported as unchanged.

Inputs: path (required), nodes, value, values, +1 more.

signal_statsA
Read-onlyIdempotent

Scalar summary of one signal in a .raw result. Use this when you need a single number per metric (average, RMS, peak, etc.) — not a waveform or a trend.

Transient: time-weighted mean, RMS, std, abs-mean, and min/max/pk-pk using trapezoidal integration (RMS = sqrt(∫ y² dt / T)). This is correct on SPICE's adaptive timestep — simple np.mean(y) would overweight densely sampled regions. Optionally restrict to [t_start, t_end]; passing no window averages the whole waveform including any startup transient, which is usually wrong for RMS/mean.

DC: returns min/max/pk-pk and the simple/abs mean over the swept axis, plus sweep_start_used/sweep_end_used/sweep_span. RMS and std are deliberately omitted — they're meaningless on a non-time axis. Use t_start/t_end to restrict the sweep range.

AC: returns magnitude (dB) min/max/mean and phase (deg) min/max. t_start/t_end are rejected for AC — use query_value for a point at a specific frequency.

Noise: returns min/max/pk-pk of the noise spectral density over the frequency axis, plus freq_start_used/freq_end_used. Mean, RMS, std, and duration are omitted — a plain mean of spectral density is dominated by sample clustering and the sweep span, not the circuit; min/max is the useful worst-case reading. t_start/t_end are rejected — pass them via query_value at specific frequencies instead.

Related tools: for rise/fall times use edge_metrics; for overshoot/settling use pulse_response; for period/duty use periodic_metrics; to aggregate .MEAS values across a sweep use measurement_stats.

Inputs: signal (required), step, t_end, format, +4 more. Returns: max, min, rms, std, +20 more

simulation_summaryA
Read-onlyIdempotent

Get a comprehensive simulation summary including type, signal list, data size, .MEAS results, Fourier analysis, AC bandwidth metrics, and warnings.

Inputs: step, format, job_id, signal, +3 more. Returns: range, errors, fourier, signals, +9 more

stability_metricsA
Read-onlyIdempotent

Find EVERY unity-gain and -180° phase crossover in a loop-gain AC sweep, report phase margin at each unity-gain crossing and gain margin at each -180° crossing. Replaces the single-crossing approximation in simulation_summary, which returns wrong margins on conditionally-stable systems.

Run this on a LOOP-GAIN signal (typically a dedicated middlebrook probe or .AC of the open loop). Running on a closed-loop output gives meaningless margins — if the DC phase starts near ±180° (a closed-loop / inverting output rather than a loop probe, which starts near 0°), a warning says so in warnings.

Returns: dc_gain_db, high_freq_gain_db, stability classification (stable / unstable / conditional / unconditional / always_below_unity), all crossings, per-crossing margins, and the worst-case values.

Nuances:

  • Phase is UNWRAPPED first, so systems whose phase drops past -360° are handled correctly (otherwise the raw wrap hides the crossing).

  • If phase NEVER crosses -180°, gain margin is 'infinite' (returned as null with stability='unconditional'). That's stable, not an error.

  • If gain NEVER reaches unity, phase margin is undefined (returned as null with stability='always_below_unity').

  • Multiple crossovers trigger stability='conditional' and a warning — each one needs its own review.

For -3 dB filter cutoffs use bode_metrics(mode='filter'); for custom crossings use bode_metrics(mode='crossing').

Inputs: signal (required), step, format, job_id, +3 more. Returns: signal, warnings, stability, dc_gain_db, +7 more

symbol_infoA
Read-onlyIdempotent

Get symbol pin positions, bounding box, and description. Optionally compute absolute positions for a given placement and rotation.

Inputs: symbol (required), x, y, format, +1 more. Returns: name, pins, placement, bbox_width, +4 more

thdA
Read-onlyIdempotent

Total harmonic distortion (THD and THD+N) of a periodic transient signal via FFT — works on any .tran result without a .four directive in the deck, and on any simulator. Defaults to COHERENT sampling (record trimmed to whole fundamental cycles, rectangular window) so harmonics land exactly on bins and THD is exact; window='hann' is the approximate fallback. Surfaces every condition the number depends on: the fundamental (given vs auto-detected), window kind, cycles analyzed, FFT length, sample rate, and per-harmonic levels. For LTspice's own .four result instead, see simulation_summary's Fourier section.

Inputs: signal (required), step, t_end, format, +7 more. Returns: fs_hz, n_fft, signal, thd_db, +12 more

timing_betweenA
Read-onlyIdempotent

Use when you need propagation delay / skew between TWO signals — e.g. input-to-output delay, clock-to-Q, input-skew. Inputs one transient .raw containing both signals on a shared time axis.

Returns: signed delay = t_b - t_a where t_a and t_b are the FIRST threshold crossings of signal_a and signal_b in the window. Negative delay means signal_b leads signal_a.

Thresholds default to 50% of EACH signal's own min-max range in the window — intentional for asymmetric CMOS where V_in and V_out have different rails. Override per-signal via threshold_a / threshold_b if you need absolute thresholds (e.g. VIH/VIL at fixed voltages). Set direction_a / direction_b independently (e.g. rising input → falling output for an inverter).

Picks only the FIRST crossing of each signal in the window — if both signals have multiple edges, tighten t_start/t_end around the specific edge pair you want. Rejects AC analysis.

Inputs: signal_a (required), signal_b (required), step, t_end, +10 more. Returns: t_a, t_b, delay, signal_a, +8 more

trace_netA
Read-onlyIdempotent

Report everything electrically connected to a net: starting from a pin ('Ref.Pin'), a net label ('net:NAME'), or an (x,y) coordinate, return the net's labels and every component pin, FLAG, and wire vertex on it. Follows both wires (segment-aware — catches labels placed mid-wire) and same-name FLAGs (LTspice's name-based nets). Use it to answer 'what's on net X', to confirm a connect landed, or to spot an accidental short (a net carrying two different non-ground labels).

Inputs: path (required), x, y, pin, +1 more. Returns: pins, start, labels, is_shorted, +1 more

unload_libraryA
Idempotent

Unload a previously loaded library from the session.

Inputs: path (required).

validate_netlistA
Read-onlyIdempotent

Lint a netlist or schematic before simulation — the static circuit check gate. Catches: empty/whitespace-only netlist files, element arity (too few nodes, missing E/G/F/H/B value), dangling nodes in .cir/.net netlists (a node touching only one element terminal — warning, since deliberate fragments are legal), bias-topology degeneracies in .cir/.net netlists (a net with no DC path to ground — floating MOSFET gate, capacitive island, current-source-only node, or isolated domain — warning, since the operating point may still be defined by other means), duplicate/multiple analysis directives ('More than one analysis specified'), .MEAS whose analysis kind isn't present, known-bad .MEAS patterns (vdb()/phase()/group_delay()), and directives the LTspice runner is known to reject (set target_simulator='ngspice' to instead flag ngspice-only incompatibilities, e.g. a zero '.tran' step time). On .asc, also surfaces named-net shorts, floating pins, and dangling labels. Returns a structured issue list; an empty list means the file passes the static gate. Note: value tokens (e.g. a typo'd '1kk') and undefined model references are NOT checked — LTspice coerces or resolves those at run time.

Inputs: path (required), format, target_simulator. Returns: file, issues, issue_count

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    B3.2/5.0

    Scored across 49 tools

    Disambiguation4/5

    Most tools have clearly distinct purposes, with detailed cross-referencing that resolves potential confusion (e.g., get_waveform vs export_waveform vs plot_waveform). A few overlaps exist—such as run_sweep/run_montecarlo and the various AC analysis tools—but the descriptions explicitly delineate when each should be used.

    Naming Consistency4/5

    All tool names follow a snake_case convention with a mostly verb_noun pattern (run_simulation, list_components, set_component_value). A few names are nouns or adjectives (resonance, operating_point, recent, parameter), but the overall style is consistent and readable.

    Tool Count2/5

    49 tools is a very large surface for an MCP server, exceeding the 25+ threshold where coherence tends to degrade. While the domain is broad (simulation, analysis, schematic editing, libraries), the sheer number makes navigation and selection harder.

    Completeness5/5

    The tool set covers the full LTspice workflow: circuit creation/editing, netlist validation, simulation execution (single, sweep, Monte Carlo), job management, comprehensive signal analysis (time/frequency/AC/noise), and library management. There are no obvious dead ends; every core operation has a corresponding tool.

    Maintenance

    ActivityInactive
    ResponsivenessOutdated data

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      B
      quality
      D
      maintenance
      AI-powered circuit design through simulation — an MCP server that gives language models direct access to SPICE circuit simulation via ngspice, enabling natural language circuit description and automated netlist generation, simulation, measurement, and spec verification.
      28
      141 PyPI
      45
      GPL 3.0
    • F
      license
      C
      quality
      C
      maintenance
      MCP server for automating LTspice on macOS, enabling simulation, schematic generation, data extraction, verification, and rendering via natural language or agents.
      71
      21
      -
    • A
      license
      A
      quality
      B
      maintenance
      An MCP server that connects LLM assistants to real circuit simulation: LTspice and ngspice, plus direct editing of LTspice .asc schematics. Simulation results come back as structured numbers so the assistant can design, verify, and iterate on circuits.
      48
      451 PyPI
      72
      GPL 3.0