scpi-mcp
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@scpi-mcpCapture the signal on channel 1"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
scpi-mcp
LabLink gives agents a SCPI wire; scpi-mcp gives agents oscilloscope expertise.
scpi-mcp is a Model Context Protocol server
that lets an agent operate an oscilloscope โ not just push SCPI strings at one.
It exposes goal-level tools (capture this signal, measure that, characterize a
channel) backed by a clean, instrument-agnostic interface. All vendor SCPI lives
in the underlying instrument library; the MCP layer stays a thin, uniform wrapper
with no raw-SCPI escape hatch.
.-"""-.
/ .===. \ Skippi ๐งโโ๏ธ
\/ 6 6 \/ the artistic scope gremlin
( \___/ ) "every waveform is a portrait of the magic pixies"
___ooo___ooo___Skippi is the mascot โ the artistic gremlin who lives in the scope and paints pictures of the magic pixies (the ones who carry every electron down the probe). When you see a clean trace, that's Skippi's latest masterpiece.
Scope
First instrument: Rigol DS1054Z (unlocked to DS1104Z base) โ 4 analog
channels, 100 MHz. No :SOURce (function generator) or :LA (logic analyzer)
support. Reachable over USB or LAN (TCPIP::<ip>::INSTR).
Related MCP server: rigol-mcp
Architecture
transport/โ owns discovery. Enumerates USB, falls back to best-effort LAN auto-discovery, then to an IP prompt; resolves a single VISA resource string and hands it to the instrument layer. Discovery never leaks upward.instruments/โ vendor-specific backends behind one abstractbase.pyinterface.rigol_ds1000z.pyis a thin wrapper over the (complete) library;mock.pyimplements the same interface with zero hardware. Adding an instrument is one new file here and zero changes totools/.tools/โ instrument-agnostic MCP tools that call onlybase.py.config.pyโ permission tiers (read_only/read_config/full), enforced at the tool layer. The server refuses; the model never decides.
Status
Live hardware, active bench use. The Rigol DS1054Z is connected and scpi-mcp is driving real measurements โ see Skippi in the Wild for captures. The mock backend remains available for development and CI.
Quickstart
uv sync
uv run pytest # all green against the mock, zero hardware
uv run scpi-mcp # start the MCP server (mock backend by default)Skippi in the Wild
Real captures from the bench, analyzed live via scpi-mcp.
Power-off โ relay coil with freewheel diode
The setup: A 24 V relay coil (with freewheel diode installed) powered from a bench supply. Probed at the moment of power-off to observe inductive kickback. CH1 watches the supply rail; CH2 sits across the freewheel diode.
Prompts used:
Grab the scope screen.
What are the min and max voltages on each channel?
Is that spike on CH2 actually 60 V, or is the scale messing with me?scpi-mcp called capture_screen and measure_snapshot, then explained the
visual illusion: CH2 is set to 1 V/div, so its 5.36 V kickback spike fills
5+ of the 8 vertical divisions and looks enormous. CH1 is at 8 V/div, so
the 24 V rail only occupies ~3 divisions despite being far larger in absolute
terms. No 60 V spike โ the freewheel diode clamped it cleanly to
V_supply + V_f โ 24.7 V, right where it should be.

500 ms/div (5 s full sweep). CH1 yellow, 8 V/div: 24 V supply decaying from 26.9 V โ 2.24 V. CH2 cyan, 1 V/div: freewheel diode kickback, max 5.36 V, min โ2.08 V.
Power-off โ bare coil, no freewheel diode
The setup: The same 24 V relay coil, but with the freewheel diode removed โ a bare inductor. Powered from a bench supply (100 nF across the rail to tame switch-mode ripple). Two 10x probes straddle the disconnect on the high side: CH1 on the supply side, CH2 on the coil side. Power is cut by pulling the + lead, and a single-shot trigger catches the unclamped kickback.
Prompts used:
Prime the scope for a single-shot on CH2 falling โ I'll pull the + lead.
We didn't clear the clipping โ reset V/div on CH2 and re-arm for another one-shot.
Got it โ grab the screencap and give me the true peak.scpi-mcp armed a single-shot falling-edge trigger on CH2, watched the trigger status, and grabbed the screen plus both channel waveforms the instant it fired. This time the scale fought back the other way: the kick kept overflowing the window โ it railed at ยฑ130 V, then again at โ304 V โ so scpi-mcp stepped CH2 coarser to 100 V/div until the whole transient fit. With no freewheel diode to absorb it, the collapsing field threw a โ436 V spike with a +240 V overshoot โ a ~676 Vpp ring, roughly 18x the 24 V rail โ then bled off exponentially back toward the rail over ~1 ms. Compare the clamped case above, where the diode held the same coil to โ24.7 V.

200 ยตs/div. CH1 yellow, 20 V/div: supply side holds ~24 V with a small coupled ring at the break. CH2 cyan, 100 V/div: bare-coil kickback โ peak โ436 V, +240 V overshoot (~676 Vpp), then exponential bleed-back. No freewheel diode; contrast the โ24.7 V clamped result above.
License
MIT
Maintenance
Latest Blog Posts
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/armchairdeity/mcp-server-scpi'
If you have feedback or need assistance with the MCP directory API, please join our Discord server