SRS Lock-in Amplifier — MCP Server
Let an AI agent read X/Y/R/θ, set the reference frequency, harmonic and phase, drive level, sensitivity and time constant, run auto phase/gain, and record bounded frequency sweeps on Stanford Research Systems DSP lock-in amplifiers, both the classic SR810/SR830 and the current SR860/SR865A.
| Package | labmcp-srs-lockin |
| Instruments | SR830, SR810 (SR8x0 command set); SR860, SR865A (SR86x command set) |
| Interfaces | GPIB (VISA), RS-232; SR86x also USB (USBTMC) and Ethernet (VXI-11) |
| Protocol | SRS ASCII remote commands, IEEE-488.2 style (SR830 manual ch. 5, SR810 manual, SR860 manual ch. 4, SR865A manual) |
| Status | 🧪 simulated: tested against a wire-level simulator of both command sets, not yet verified on hardware. Report a hardware test |
Try it without hardware
uvx labmcp-srs-lockin --simulate --check # SR830 simulator
uvx labmcp-srs-lockin --simulate --option model=sr860 --check # SR860 simulator
The simulated sample is a resonator (10 kHz, Q = 50) driven by the sine output, so a frequency_sweep from 9 to 11 kHz shows a resonance peak.
Connect your lock-in
The model is detected from *IDN? (override with --option model=sr830|sr810|sr860|sr865a).
- GPIB (all models): set the GPIB address in the setup menu (SR830 factory default 8). Install
labmcp[visa](included) and a VISA backend (pyvisa-py works with most USB-GPIB adapters; NI-VISA with?backend=@ivi). - RS-232: set baud rate and parity on the instrument (SR830 default 9600 baud, no parity; the word length is always 8 bits). The SR830 only answers on the interface selected by
OUTX; the server sendsOUTX 0automatically on serial connections andOUTX 1on GPIB. The SR830 ends RS-232 replies with CR. For an SR86x on RS-232, pass--option model=sr860(replies end with LF) or set the SR86x transmit terminator to CR. - SR86x USB / Ethernet: use the USBTMC or VXI-11 VISA resource (
TCPIP0::<ip>::inst0::INSTR; enable VXI-11 and add your PC to the trusted IP range in the system menu). - Test the connection:
uvx labmcp-srs-lockin --address GPIB0::8::INSTR --check uvx labmcp-srs-lockin --address /dev/ttyUSB0 --check # SR830 RS-232 uvx labmcp-srs-lockin --address "serial://COM3?baudrate=19200" --check # non-default baud uvx labmcp-srs-lockin --address TCPIP0::192.168.1.20::inst0::INSTR --check # SR86x LAN
Use--option interface=gpibif you reach an SR830's GPIB port through a raw TCP adapter.
Add to your MCP client
Claude Code
claude mcp add lockin -- uvx labmcp-srs-lockin --address GPIB0::8::INSTR
Claude Desktop / Cursor / Windsurf (claude_desktop_config.json, .cursor/mcp.json, …)
{
"mcpServers": {
"lockin": {
"command": "uvx",
"args": ["labmcp-srs-lockin", "--address", "GPIB0::8::INSTR"]
}
}
}
Add --read-only to allow reading outputs and settings but block every setting change and the sine-output drive. For other clients, generate the snippet with uvx labmcp config srs-lockin --address GPIB0::8::INSTR --client vscode (also cursor, codex, claude-code).
Tools
| Tool | Kind | Description |
|---|---|---|
auto_gain |
🎛 control | Pick the sensitivity automatically for the present signal (SR830 AGAN / SR86x ASCL). On the SR830 AGAN does nothing when the time constant is longer than 1 s. |
auto_phase |
🎛 control | Run Auto Phase (APHS): shift the reference phase so that Y ≈ 0 and X ≈ R. The outputs then need several time constants to settle. Does nothing if the phase is unstable. |
auto_range |
🎛 control | Optimise the input stage for the present signal: SR830 Auto Reserve (ARSV) or SR86x Auto Range of the voltage input range (ARNG). |
frequency_sweep |
⚠️ hazard | Step the internal reference (and SINE OUT drive) from start_hz to stop_hz, waiting for the output filter to settle at each point, and record X/Y/R/θ vs frequency - e.g. a resonance or transfer-function measurement. The drive amplitude stays at its present value. Needs the internal reference. The estimated duration must be within max_sweep_duration_s; set_amplitude_minimum stops a running sweep. save_path must be a new .csv file. |
get_command_log |
👁 read | Return the most recent raw commands sent to / replies received from the instrument (newest last). Useful for debugging and for recording what was done. |
get_connection_info |
👁 read | Report which instrument is connected (identity, address, simulated or real), whether the server is read-only, and the active safety limits. Call this first. |
get_settings |
👁 read | Report the reference (source, frequency, harmonic, phase), sine output, sensitivity, time constant/slope (with the 99 % settling time), and input configuration. |
read_outputs |
👁 read | Read X, Y, R and θ as one coherent snapshot (SNAP?), with the reference frequency, sensitivity, fraction of full scale and any overloads latched since the last reading. |
reconnect |
🛑 safety | Close and re-open the connection to the instrument (e.g. after it was power cycled or a cable was re-plugged). |
set_amplitude |
⚠️ hazard | Set the SINE OUT amplitude (V rms), which drives the sample or excitation circuit. Refused above the max_amplitude_v safety limit. Tell the user the new drive level first. |
set_amplitude_minimum |
🛑 safety | Turn the sine output down to the instrument minimum (the lock-in's closest thing to 'output off') and stop any running frequency sweep. SR810/SR830: 4 mV rms (it cannot go to zero - disconnect the cable if the sample must see no drive). SR86x: 1 nV rms and DC level 0 V. |
set_input |
🎛 control | Configure the signal input: A / A-B / current, AC or DC coupling, shield float/ground and (SR86x) the voltage input range. Use DC coupling below ~160 mHz. Omitted parameters are left unchanged. |
set_reference |
🎛 control | Set the reference: source (internal/external), internal frequency, detection harmonic and phase shift. Omitted parameters are left unchanged. Changing the frequency also changes the frequency of the SINE OUT drive (at the current amplitude). |
set_sensitivity |
🎛 control | Set the sensitivity (full-scale range). The smallest available range that is at least full_scale is chosen, so a signal of that size does not overload. On SR810/SR830 the dynamic reserve can be set at the same time. |
set_time_constant |
🎛 control | Set the output filter time constant (nearest available value), and optionally the filter slope and synchronous filter. The SR830 may raise a too-short time constant to its minimum for the current slope/reserve; the returned settings show the value actually used. |
get_connection_info, get_command_log and reconnect are built into every LabMCP server.
Safety limits
| Limit | Default | Meaning |
|---|---|---|
max_amplitude_v |
1.0 V | Largest sine-output amplitude (V rms) set_amplitude may set; a sweep also refuses to run if the present amplitude is above it |
max_sweep_duration_s |
600 s | Longest estimated frequency sweep (points × settle time) an agent may start |
Override at launch: --limit max_amplitude_v=0.1 --limit max_sweep_duration_s=1800.
Example prompts
- "Set the lock-in to 13.7 Hz internal reference, 100 mV drive, 1 s time constant at 24 dB/oct, and tell me X and Y once it has settled."
- "Auto-phase, then read R and θ ten times and give me the mean and standard deviation of R."
- "Sweep the drive from 30 to 34 kHz in 201 log-spaced steps at 10 mV and find the resonance frequency and Q of my tuning fork."
- "Switch to the current input with 100 MΩ gain, DC coupling, and pick the sensitivity automatically."
- "We're done - turn the sine output down to the minimum."
Notes
- The sine output is the hazard. It drives your sample (heating, electromigration, piezo stress).
set_amplitudechecksmax_amplitude_v;set_amplitude_minimumis the closest thing to "output off": the SR810/SR830 cannot go below 4 mV rms, so disconnect the cable if the sample must see no drive. On the SR86x it sets 1 nV rms and a 0 V DC level (SOFF). The SR830 powers up and resets (*RST) to 1.000 V rms. - Every set command is followed by
*ESR?; if the lock-in flags an execution error (parameter out of range, e.g.FREQin external-reference mode) or an illegal command, the tool reports it instead of silently continuing. set_sensitivitypicks the smallest range that is at least the requested full scale (never a smaller one, which would overload).set_time_constantpicks the nearest available value; the SR830 may raise it to the minimum allowed for the slope/reserve, and the returned settings show the value actually used.read_outputsreturnsunit= V for voltage inputs and A for the current input (1 V ↔ 1 µA sensitivity mapping from the manuals). The SR830 manual (SR530-compatibilityQX/QYcommands, ch. 5) states that outputs are returned in amps when the current input is selected; the SR86x manual does not say explicitly — please report what your instrument returns.overloadscomes fromLIAS?, whose bits are latched since the last read; the first reading after a transient may show an overload that has already cleared.frequency_sweepwaits the manual's 99 % settling time at each point (5/7/9/10 time constants for 6/12/18/24 dB/oct) unlesssettle_time_constantsis given, and restores the starting frequency afterwards. Callingset_amplitude_minimumstops a running sweep at the next point (also one that is still reading its settings). One sweep can take at most 3640 s (the tool's timeout minus a margin) whatevermax_sweep_duration_sis: longer estimates are refused, and a sweep running slower than estimated stops early and returns the points measured so far (completed: false).save_pathmust end in.csvand must not exist yet (an existing file is never overwritten); it is checked before the sweep starts.set_amplitude_minimumtries both the amplitude and (SR86x) the DC level even if one of them fails, then reports every failure.auto_gainmaps toAGAN(SR830) orASCL(SR86x);auto_rangemaps toARSV(SR830 auto reserve) orARNG(SR86x auto input range). SR830AGANdoes nothing when the time constant is above 1 s.- Data-buffer, streaming and FFT functions are not exposed. The SR850, SR844 (RF) and SR865 (non-A) are not included because they were not verified; an explicit
--option model=...lets you try a compatible model at your own risk.
Hardware verification
| Model | Firmware | Interface | Verified by | Date |
|---|---|---|---|---|
| none yet: be the first |
Release files for labmcp-srs-lockin 0.1.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| labmcp_srs_lockin-0.1.2.tar.gz | 26.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| labmcp_srs_lockin-0.1.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 51.6 kB
Release files / labmcp_srs_lockin-0.1.2.tar.gz
| Download URL | labmcp_srs_lockin-0.1.2.tar.gz |
|---|---|
| Size | 26.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
0ca428151c2801562332d26d4a801bb6a5e1bd4eae4dd1dac9ddfd04dc48a4a0
|
|
BLAKE2b-256 checksum How to use checksums |
126143bc5fb91e6e1d2d5230ae07e6ff8556387d13fa54520e6aeb52c654c6fb
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 26, 2026.
Transparency logRelease files / labmcp_srs_lockin-0.1.2-py3-none-any.whl
| Download URL | labmcp_srs_lockin-0.1.2-py3-none-any.whl |
|---|---|
| Size | 24.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
ac802c02d80a8be5061a6b6fe215ac2d5457d107ee69e16e11bcb7c80d6b419b
|
|
BLAKE2b-256 checksum How to use checksums |
4f1276899ddf587078d7de018ededcfa14925f105ba7e163d1953ce2341de71b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 26, 2026.
Transparency log