Circuit StudioAgents

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.

MCPhttps://circuit.synthcity.org/api/mcp

Streamable 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 Code
claude mcp add --transport http circuit-studio https://circuit.synthcity.org/api/mcp

ChatGPT

Turn on developer mode (Settings → Apps → Advanced), create an app with the URL above and choose No authentication.

Codex

Codex
codex mcp add circuit-studio --url https://circuit.synthcity.org/api/mcp

Anything 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:

Prompt
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:

  1. gallery finds the circuit; open returns its netlist and a share link.
  2. sensitivity shows which parts move the cutoff and the peak.
  3. optimize on R1, R2, C1 and C2 with target: {type: "lowpass", cutoffHz: 800, q: 0.9}, snap: "E24", apply: true returns the retuned circuit.
  4. simulate with input: "saw:A2" and measures: ["response"] confirms the cutoff and links the audio.
  5. render_image draws 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: true

input 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: true

Find 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.

newCreate an empty circuit; returns its netlist and share link.
openOpen a gallery or preset circuit by name, netlist text, or a share link; returns its netlist and share link.
addPartAdd 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).
removePartDelete a part and the wire stubs that only served it (a module: its cables and its definition when unused).
setValueSet a part value (engineering units), a pot (total value, or pos=0..1 for the wiper), or a .param by name.
rotateRotate a part by quarter turns (and/or mirror it); its wires re-route.
moveMove a part to a grid position; its wires re-route.
connectConnect 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.
disconnectDisconnect a pin from its net (the rest of the net stays connected and is re-routed).
macro_createCollapse parts into a new .subckt macro block (nets leaving the group become ports).
macro_expandReplace a macro block with its parts, laid out where the block was.
layoutRe-arrange the whole schematic with the importer's automatic layout (layered placement, then routing).
listList parts (with pins and nets), nodes, knobs, ;@ bindings, .params, models and subcircuits, and for patches the modules, jacks and cables.
netlist_exportExport the netlist: cir (circuit-runtime, with *@cs layout), spice (no layout) or ngspice (op-amp / OTA / inverter cards translated).
simulateRun 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).
fitFit 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).
sensitivityHow 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.
acSmall-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).
optimizeChoose 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_imageDraw the schematic with the editor's renderer: PNG (returned as an image) or SVG text.
validateCheck connectivity (unconnected pins, floating nodes, ground), models and subcircuits, that circuit-runtime builds it, and that it converges on a test signal.
galleryList the bundled example circuits (open any by name).
blocksList the modules addBlock can place: built-ins (VCO, LFO, Envelope, VCA, Mixer, Keyboard, ...) and every preset filter, oscillator and effect as a module.
addBlockPlace 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).
patchPatch 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.
unpatchRemove the cables on a jack ("VCF1.in").
setKnobTurn 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).
swapSwap 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.
bypassBypass a module (its audio input passes straight to its output; modules without audio are muted) or bring it back.
outputOutput monitoring: mono or stereo (stereo adds the right Output), and pan (-1..1).
mixerConfigure a Mixer module: channel count and mono / stereo (cables re-patched where they still fit).
voicesKeyboard voices: 1 (mono), 2 or 4 independent circuit voices, legato, or expand the voices into editable circuit copies.
plugin_exportExport 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.
shareA 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.
bomBill of materials (a schematic inventory: reference, value, kind, quantity), as rows or CSV.
analyseThe 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_responseResponse 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_controlMeasured 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.
auditKnob 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 simulate at 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 fit or optimize call, and a fit budget 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).

PlaceholderThe local door lives in a private repository. How to get access will be described here.