Circuit Studio for agents
An open MCP server for analog audio circuits. Your assistant can build a circuit, simulate it with the engine the app plays through, measure it, draw it, and tune its values.
https://circuit.synthcity.org/api/mcpStreamable HTTP. No account, no key.
Build
Start from a gallery circuit or a blank sheet. Add parts, connect pins, change values.
Hear and measure
Simulate a note or a sweep. Get WAV audio, levels, spectra and the frequency response.
Tune
Pick values for a target response, or match a recording of real hardware.
Connect
Claude
On claude.ai: Settings → Connectors → Add custom connector, and paste the URL above. In Claude Code:
claude mcp add --transport http circuit-studio https://circuit.synthcity.org/api/mcpChatGPT
Turn on developer mode (Settings → Apps → Advanced), create an app with the URL above and choose No authentication.
Codex
codex mcp add circuit-studio --url https://circuit.synthcity.org/api/mcpAnything else
Any MCP client that speaks streamable HTTP. Point it at the URL; nothing else to configure.
Design a filter with an agent
Ask in plain words:
Open the Sallen-Key low-pass from the Circuit Studio gallery. Retune it to
800 Hz with Q 0.9 using E24 parts, then play a saw through it and show me
the schematic.What the agent does:
galleryfinds the circuit;openreturns its netlist and a share link.sensitivityshows which parts move the cutoff and the peak.optimizeon R1, R2, C1 and C2 withtarget: {type: "lowpass", cutoffHz: 800, q: 0.9},snap: "E24",apply: truereturns the retuned circuit.simulatewithinput: "saw:A2"andmeasures: ["response"]confirms the cutoff and links the audio.render_imagedraws it. The share link opens the result in the app.
Fit, optimize, sensitivity
The simulator is differentiable: it gives exact gradients of the sound with respect to every part value. Three tools use this. They have no button in the app; agents and the API are the way in.
Match a recording: fit
Record a pedal or filter: the signal you sent in and what came out. fit finds the part values and pot positions that reproduce it, can snap them to E12 or E24, and says which values the audio cannot pin down.
fit doc: "<your circuit>"
input: "data:audio/wav;base64,…"
target: "data:audio/wav;base64,…"
params: ["R4", "C2", "P1.pos"]
snap: "E24" apply: trueinput is the dry signal, target the recording.
Hit a response: optimize
Give a prototype (low-pass, high-pass or band-pass with cutoff, Q, gain) or a list of [Hz, dB] points. Give several knob settings to tune one set of parts for all of them.
optimize doc: "sallen-key-lpf" params: ["R1", "R2", "C1", "C2"]
target: {type: "lowpass", cutoffHz: 800, q: 0.9}
snap: "E24" apply: trueFind what matters: sensitivity
For each part: how far the cutoff moves per percent of change, and how much the peak and passband move in dB.
sensitivity doc: "sallen-key-lpf"
→ R1 cutoff −0.50 % per %
C1 cutoff +0.21 % per %
C2 cutoff −1.21 % per % …Tools
Every tool the hosted server offers, from the same tool layer as the app's API and CLI. Live schemas: tools.json or the server's tools/list.
new | Create an empty circuit; returns its netlist and share link. |
open | Open a gallery or preset circuit by name, netlist text, or a share link; returns its netlist and share link. |
addPart | Add a part: R, C, L, POT, D, NPN, PNP, NJF, PJF, OPAMP, OTA, V, I, IN (audio input), OUT (output probe), GND, RAIL, LABEL, or macro:<NAME> (built-ins: OPAMP_MACRO, OTA_PAIR, OTA_POLE, DIODE_LIMITER, SALLEN_KEY, or any .subckt in the document). |
removePart | Delete a part and the wire stubs that only served it (a module: its cables and its definition when unused). |
setValue | Set a part value (engineering units), a pot (total value, or pos=0..1 for the wiper), or a .param by name. |
rotate | Rotate a part by quarter turns (and/or mirror it); its wires re-route. |
move | Move a part to a grid position; its wires re-route. |
connect | Connect a pin to another pin or to a net (gnd, a rail name like Vcc, or any net name). Wires are auto-routed with the editor's A* router; long or blocked runs get net labels. |
disconnect | Disconnect a pin from its net (the rest of the net stays connected and is re-routed). |
macro_create | Collapse parts into a new .subckt macro block (nets leaving the group become ports). |
macro_expand | Replace a macro block with its parts, laid out where the block was. |
layout | Re-arrange the whole schematic with the importer's automatic layout (layered placement, then routing). |
list | List parts (with pins and nets), nodes, knobs, ;@ bindings, .params, models and subcircuits, and for patches the modules, jacks and cables. |
netlist_export | Export the netlist: cir (circuit-runtime, with *@cs layout), spice (no layout) or ngspice (op-amp / OTA / inverter cards translated). |
simulate | Run the circuit on circuit-runtime: an input source, knob automation, audio out (wav/f32), node probes, and measures (level, spectrum peaks, frequency response with cutoff / slope / peak / notches). |
fit | Fit component values / device parameters / pot positions so the circuit reproduces a recording: target audio + the input that produced it. Gradient-based (Levenberg-Marquardt in log-values, or L-BFGS / Adam), with bounds, optional E-series snapping and an identifiability report (which parameters the audio cannot pin down). |
sensitivity | How each part moves the small-signal response: cutoff (% per %), peak, prominence and passband (dB per %), from exact gradients of the simulator at its operating point. |
ac | Small-signal response (dB, phase, complex) at chosen frequencies, at chosen knob positions, with its exact Jacobian with respect to the listed parameters (from the simulator's linearised step map, operating-point shift included). |
optimize | Choose values so the small-signal response meets a target: a prototype (lowpass / highpass / bandpass, cutoff, Q, gain, order) or [Hz, dB] points, at one knob setting or at several at once (settings: one target per knob setting, one shared set of values). Optional E-series snapping (most sensitive part first, the rest re-polished after each rounding); apply writes the values into the document. |
render_image | Draw the schematic with the editor's renderer: PNG (returned as an image) or SVG text. |
validate | Check connectivity (unconnected pins, floating nodes, ground), models and subcircuits, that circuit-runtime builds it, and that it converges on a test signal. |
gallery | List the bundled example circuits (open any by name). |
blocks | List the modules addBlock can place: built-ins (VCO, LFO, Envelope, VCA, Mixer, Keyboard, ...) and every preset filter, oscillator and effect as a module. |
addBlock | Place a module (patch level): a built-in (vco, lfo, env, vca, mixer, keyboard, drive, ...) or any preset filter / oscillator / effect by name. Like the app, a new module gets the Keyboard's pitch / gate when it has those jacks (the Keyboard appears if missing). |
patch | Patch a cable between two module jacks ("VCO1.out" → "VCF1.in"; "in" / "out" are the audio input and output). Like the app, a cable onto an occupied input replaces the old one. |
unpatch | Remove the cables on a jack ("VCF1.in"). |
setKnob | Turn a knob (the knob tray / a module face): a 0..1 position, or a value in the knob's unit ("1.2k" Hz, "40" %). Module knobs are "<module> <label>" or the param (VCF1_IABC). |
swap | Swap a module, circuit block or device in place, keeping its connections (the app's swap menus): a module for another of its kind (cables re-patched by role, knobs carried by meaning), a schematic block for another circuit, or a device model (BBD chip, op-amp, transistor, diode, vactrol). Without "to", lists the choices. |
bypass | Bypass a module (its audio input passes straight to its output; modules without audio are muted) or bring it back. |
output | Output monitoring: mono or stereo (stereo adds the right Output), and pan (-1..1). |
mixer | Configure a Mixer module: channel count and mono / stereo (cables re-patched where they still fit). |
voices | Keyboard voices: 1 (mono), 2 or 4 independent circuit voices, legato, or expand the voices into editable circuit copies. |
plugin_export | Export the circuit or patch as a WebCLAP plugin bundle (.wclap: frozen WASM engine + circuit + metadata), the same bundle as the app's plugin export. Effects take audio; patches with a Keyboard become instruments. |
share | A share link: the whole document in the URL fragment (circuit.synthcity.org/#c=…, made offline, never sent to a server), or the preset page for an unedited gallery circuit. short: true also uploads an immutable snapshot (/s/<id>) — only when asked. |
bom | Bill of materials (a schematic inventory: reference, value, kind, quantity), as rows or CSV. |
analyse | The analysis panel's measurement in raw node volts (before output scale and limiter): a frequency response (stepped sine) or a transient (sine / step / DC) at any node. |
design_response | Response design (the app's Design tab): pick resistor / capacitor values within bounds so the measured response meets [Hz, dB] targets; E12/E24 values; apply writes them. A bounded local search on the real circuit (no small-signal assumption). |
diagnose_control | Measured control diagnostics (the app's Diagnose tab): does a knob change a node at nominal and quiet drive, or is its effect masked by clipping / compression? Gain, THD and a plain conclusion per node. |
audit | Knob and stability audit: every knob at a few positions must change the sound measurably (inert knobs, release-only knobs, live/commit mismatches flagged), and a stability sweep across knob corners. |
Not on the hosted server: save (needs the local file system or local tools); close (nothing to close: each hosted call is stateless); spice, spice_study (SPICE: ngspice-wasm compiles its WebAssembly at run time, which Cloudflare Workers do not allow).
Passing circuits
Each call stands alone. Pass the circuit in doc as any of:
- Netlist
- The .cir text (starts with
*or spans lines) - Gallery
- A name or file from
gallery, e.g.sallen-key-lpf - Share link
https://circuit.synthcity.org/#c=…,/p/<preset>or/s/<id>
Every edit returns circuit.cir and circuit.link. Pass either to the next call; open the link to see it in the app.
Limits
- Audio
- 10 s per
simulateat 48 kHz (480k samples), sample rate up to 96 kHz - Recordings
- Mono WAV as a
data:audio/wav;base64,…URI, up to 10 s at 48 kHz - Tuning
- 100 iterations per
fitoroptimizecall, and afitbudget of 200 (recording seconds × iterations × parameters); call again to continue - Requests
- 4 MB per request, netlists up to 256 KB; per-address rate limits
- Files
- WAV, large PNG and .wclap plugins (WebCLAP, for Merlin Studio) come back as links that expire after 24 h
Over a limit, the tool answers with an error that says what to change.
The local door
The same tools run locally as a stdio MCP server and the circuit command line, without these limits. Locally they work on .cir files on disk and add SPICE checks and the hardware tools (hw_*: prototyping, ordering and measuring a built circuit).