Drive Rohde & Schwarz spectrum and signal analyzers from any MCP-compatible AI client. TCP or VISA — 62 tools spanning frequency, bandwidth, markers, measurements (ACLR / OBW / SEM / EVM / CCDF), traces, limits, and templates.
Important
Hardware required. This MCP server controls real spectrum analyzers over SCPI (TCP or VISA). You need actual R&S FSW / FSVA / FSV / FPL hardware (or a supported Keysight / Rigol / Siglent analyzer) on the network or USB-connected to be useful. The server has no built-in simulator — it's a thin driver, not a virtual instrument.
mcp-rs-spectrum-analyzer is a Model Context Protocol
server that automates spectrum and signal analyzers over SCPI. Connect any
MCP-compatible AI assistant (Claude Desktop, Claude Code, VS Code Copilot, …)
to your test equipment for hands-free RF measurements, EMC pre-compliance
testing, and automated test sequences.
Primary target is the R&S FSW / FSVA3000 / FSV3000 / FPL1000 family (vendor-specific result parsing, family detection). A common SCPI core also covers Keysight (N90x0/UXA/PXA/MXA/EXA/CXA), Rigol (DSA800/RSA5000/RSA3000), Siglent (SSA3000X/SVA1000X), Anritsu (MS2760/MS2090), and Tektronix (RSA500/RSA600). All vendors share ~95% identical SCPI command sets.
What mcp-rs-spectrum-analyzer does well:
- 🤖 AI-native via MCP. First-class Model Context Protocol server with 62 tools across 14 categories. Any Claude / LLM agent can drive it.
- 🐍 Python + MCP surfaces. Direct driver access via
import spectrum_analyzer_mcp, or run as an MCP server for AI-agent automation. - ⚡ Two transports. Raw TCP/IP sockets (no VISA install needed) or PyVISA for GPIB / USB-TMC / HiSLIP.
- ✅ Pre-built measurement templates. Channel power, ACLR, OBW, EMI (CISPR 32 Class B), harmonics, spurious.
- 🔒 AGPL-3.0-or-later. SCPI-injection-guarded, path-traversal-protected, raw-SCPI disable flag.
uv pip install -e .
# Optional: VISA support for GPIB/USB/HiSLIP
uv pip install -e ".[visa]"Set your instrument's address via environment variable or .env file:
export SA_HOST=192.168.1.100
export SA_PORT=5025 # 5025 for R&S / Keysight / Siglent; 5555 for Rigol| Variable | Default | Description |
|---|---|---|
SA_HOST |
192.168.1.100 |
Instrument IP address |
SA_PORT |
5025 |
SCPI TCP port |
SA_TIMEOUT |
5.0 |
Connection timeout (s) |
SA_COMMAND_TIMEOUT |
10.0 |
SCPI command timeout (s) |
SA_RESOURCE_STRING |
(none) | VISA resource string (overrides host/port) |
SA_SAFE_DIRECTORIES |
["."] |
Allowed dirs for file export |
SA_MAX_EXPORT_SIZE_MB |
100 |
Max export file size |
SA_RAW_SCPI_ENABLED |
true |
Enable/disable raw SCPI commands |
|
Python import asyncio
from spectrum_analyzer_mcp.driver import SpectrumAnalyzerDriver
async def main():
async with SpectrumAnalyzerDriver("192.168.1.100", 5025) as sa:
await sa.set_center_span(1e9, 100e6)
await sa.set_reference_level(0)
await sa.set_rbw(100e3)
peak = await sa.peak_search()
print(f"Peak: {peak.frequency_hz/1e9:.4f} GHz @ {peak.amplitude_dbm:.2f} dBm")
asyncio.run(main()) |
MCP (Claude Desktop, Claude Code, any MCP client) {
"mcpServers": {
"spectrum-analyzer": {
"command": "spectrum-analyzer-mcp"
}
}
}Or for Claude Code with {
"mcpServers": {
"spectrum-analyzer": {
"command": "uv",
"args": ["run", "--directory",
"/path/to/mcp-rs-spectrum-analyzer",
"spectrum-analyzer-mcp"]
}
}
}Then ask your assistant:
|
For instruments connected via GPIB, USB-TMC, or HiSLIP (requires pyvisa):
# GPIB
await sa.connect(resource="GPIB::1::INSTR")
# USB-TMC
await sa.connect(resource="USB::0x0AAD::0x0119::100001::INSTR")
# HiSLIP
await sa.connect(resource="TCPIP::192.168.1.100::hislip0::INSTR")62 MCP tools, grouped:
| Group | Tools |
|---|---|
| Connection (5) | sa_discover, sa_connect, sa_disconnect, sa_identify, sa_get_status |
| Frequency (4) | sa_set_center_span, sa_set_start_stop, sa_set_frequency_step, sa_full_span |
| Amplitude (4) | sa_set_reference_level, sa_set_attenuation, sa_set_preamp, sa_set_scale |
| Bandwidth (4) | sa_set_rbw, sa_set_vbw, sa_set_sweep_time, sa_auto_coupling |
| Trace (5) | sa_get_trace_data, sa_set_trace_mode, sa_set_averaging_count, sa_clear_trace, sa_set_detector |
| Markers (7) | sa_set_marker, sa_get_marker, sa_peak_search, sa_next_peak, sa_marker_to_center, sa_marker_delta, sa_marker_bandwidth |
| Measurements (6) | sa_measure_channel_power, sa_measure_aclr, sa_measure_obw, sa_measure_sem, sa_measure_evm, sa_measure_ccdf |
| Sweep (3) | sa_single_sweep, sa_continuous_sweep, sa_set_trigger |
| Export (4) | sa_save_trace_csv, sa_save_trace_json, sa_save_screenshot, sa_export_trace_data |
| Raw SCPI (4) | sa_scpi_send, sa_scpi_query, sa_reset, sa_preset |
| Templates (3) | sa_list_templates, sa_load_template, sa_apply_template |
| Limits (4) | sa_define_limit, sa_check_limits, sa_clear_limits, sa_list_limits |
| State (3) | sa_save_state, sa_load_state, sa_get_full_state |
| System (6) | sa_get_error_queue, sa_set_display_update, sa_run_alignment, sa_set_sweep_points, sa_get_sweep_points, sa_capture_screenshot |
Built-in templates: channel_power, aclr, obw, emi (CISPR 32 Class B),
harmonics, spurious. Full reference in docs/tools.md.
| Vendor | Families | Transport | Status |
|---|---|---|---|
| Rohde & Schwarz | FSW, FSVA3000, FSV3000, FPL1000 | TCP, VISA | Full support |
| Keysight | N90x0, UXA, PXA, MXA, EXA, CXA | TCP, VISA | SCPI core |
| Rigol | DSA800, RSA5000, RSA3000 | TCP, VISA | SCPI core |
| Siglent | SSA3000X, SVA1000X | TCP, VISA | SCPI core |
| Anritsu | MS2760, MS2090 | TCP, VISA | SCPI core |
| Tektronix | RSA500, RSA600 | TCP, VISA | SCPI core |
Full support = vendor-specific result parsing and family detection. SCPI core = standard SCPI for frequency / amplitude / markers / trace / sweep. All vendors share 95%+ identical SCPI command sets.
- SCPI injection protection — all user-supplied parameters sanitized before inclusion in SCPI commands.
- Path-traversal protection — file-export paths validated against configured safe directories.
- Raw SCPI guard —
sa_scpi_send/sa_scpi_querycan be disabled viaSA_RAW_SCPI_ENABLED=false. - Asyncio locks — concurrent tool calls serialized per resource (connection, measurement, template).
- State rollback — failed state restore operations automatically roll back to the previous state.
mcp-rs-spectrum-analyzer fits in the following eng-mcp-suite
workflow bundles:
lab-automation— pair withcopper-mountain-vna-mcp,mcp-rs-siggen, andmcp-rs-cmw500for end-to-end RF bench-test workflows driven from a single agent session.emc-precompliance— drive ACLR / OBW / SEM measurements whilemcp-emc-regulationssupplies CISPR / FCC limits.
eng-mcp-suite install --workflow lab-automation- 📘 Quick Start — install through first call.
- 🛠️ Tool reference — every MCP tool, every argument.
- 📐 Usage examples — an EMC pre-compliance walkthrough.
- 🏗️ Architecture — how this MCP fits in eng-mcp-suite.
- 📝 Changelog
This MCP server is part of
Part of eng-mcp-suite — an open
umbrella of MCP servers for RF / EMC / PCB / signal-integrity engineering. Drop
into the lab-automation workflow bundle with
eng-mcp-suite install --workflow lab-automation.
| Domain | Sibling MCPs |
|---|---|
| RF / Transmission lines | lineforge |
| EMC regulatory | mcp-emc-regulations |
| EM simulation | mcp-openems, mcp-nec2-antenna |
| Diagrams | drawio-engineering-mcp |
| Lab gear | copper-mountain-vna-mcp · mcp-rs-spectrum-analyzer · mcp-rs-siggen · mcp-rs-cmw500 |
uv pip install -e ".[dev]"
uv run pytest tests/ -v # 250 tests
uv run ruff check src/ tests/
uv run ruff format --check src/ tests/
uv run mypy src/AGPL-3.0-or-later. Relicensed from Apache-2.0 in v0.3.0 to align with the eng-mcp-suite toolkit-wide AGPL move.
- Rohde & Schwarz — for thorough SCPI documentation of the FSW / FSVA / FSV / FPL families.
- The MCP working group — for the Model Context Protocol specification.
Part of eng-mcp-suite — built for RF engineers, PCB designers, EMC labs, and AI agents.