Signal Lab
This server does not currently have a deployable release on Glama. Follow the repository's setup instructions to install and configure it for your MCP client, including any required credentials and local dependencies.
💬 What you can ask
"What BER does 64-QAM get at 16 dB over AWGN? Check it by simulation."
"Show me a 16-QAM constellation at 20 dB with 3° of phase noise. What is the EVM?"
"Run OFDM with 64 subcarriers over a 6-tap channel at 15 dB, LS estimation vs perfect knowledge."
"How much bandwidth does a root-raised-cosine with roll-off 0.5 occupy?"
"Link budget: 20 dBm at 5.8 GHz over 300 m, 40 MHz, what capacity?"
Claude picks the tool, fills the parameters, runs it, and answers with the numbers and the plot. Every BER comes with the number of simulated bits, so you know how much to trust it.
Related MCP server: superwireless
🎛️ The front panel
Tool | What it does | Returns | |
📉 |
| BER vs Eb/N0 for BPSK, QPSK, 8PSK, 16/64/256-QAM over AWGN or Rayleigh fading, next to closed-form theory | table + scope plot |
✳️ |
| Received constellation with AWGN and phase noise | EVM, symbol error rate + plot |
📶 |
| OFDM over multipath with comb pilots, LS or perfect channel estimation | BER, channel NMSE, PAPR + plot |
👁️ |
| Root-raised-cosine shaping and matched filtering | eye opening + plot |
🌈 |
| Power spectral density of the shaped signal | 99% occupied bandwidth + plot |
📡 |
| Free-space path loss, received power, noise floor, SNR, Shannon capacity | numbers |
💡 |
| Line-of-sight gain of a visible-light link (Lambertian LED, photodiode, concentrator) | numbers |
Bad inputs come back as clear errors Claude can read and fix, for example "channel_taps must not exceed cyclic_prefix + 1, or symbols will interfere".
⚡ Plug it in
git clone https://github.com/jafarSalim/mcp-signal-lab.git
cd mcp-signal-lab
pip install -e .Claude Desktop: add this to claude_desktop_config.json (Settings → Developer → Edit Config) and restart:
{
"mcpServers": {
"signal-lab": {
"command": "python",
"args": ["-m", "signallab"],
"cwd": "/path/to/mcp-signal-lab"
}
}
}Claude Code:
claude mcp add signal-lab -- python -m signallabAny MCP client from Python (this is exactly how the tests and the validation run it):
import asyncio
from mcp.client.client import Client
from signallab.server import mcp
async def main():
async with Client(mcp) as client:
result = await client.call_tool("ber_curve", {"modulation": "16QAM", "ebn0_stop_db": 12})
print(result.content[0].text) # the numbers, as JSON
# result.content[1] is the PNG plot
asyncio.run(main())What happens on a call
%%{init: {"theme":"base","themeVariables":{"actorBkg":"#04100b","actorBorder":"#39ff14","actorTextColor":"#9cf5c7","signalColor":"#39ff14","signalTextColor":"#39ff14","noteBkgColor":"#06170f","noteTextColor":"#9cf5c7","noteBorderColor":"#1f6b4a","activationBkgColor":"#0f3b29","labelBoxBkgColor":"#04100b","labelTextColor":"#9cf5c7","loopTextColor":"#9cf5c7"}}}%%
sequenceDiagram
autonumber
actor You
participant C as Claude
participant S as Signal Lab (MCP server)
participant D as dsp.py (NumPy)
You->>C: "BER of 16-QAM at 10 dB?"
C->>S: tools/call ber_curve {modulation: 16QAM, ...}
activate S
S->>D: modulate → AWGN → demodulate, until 200 errors
D-->>S: errors / bits per Eb/N0
S->>D: closed-form theory
S-->>C: JSON table + PNG scope plot
deactivate S
C-->>You: "1.9 × 10⁻³ (simulated, 120,000 bits), theory 1.8 × 10⁻³"🧾 Calibration certificate
A lab instrument is only useful if it is calibrated. scripts/validate.py checks every simulator against closed-form theory and writes results/validation.json.
AWGN: all six modulations
Modulation | Eb/N0 points | Bits simulated | Example: simulated vs theory | Worst deviation (points with ≥ 300 errors) | |
BPSK | 6 | 5.0 M | 1.86 × 10⁻⁴ vs 1.91 × 10⁻⁴ at 8 dB | 2.8% | ✅ |
QPSK | 6 | 4.9 M | 1.96 × 10⁻⁴ vs 1.91 × 10⁻⁴ at 8 dB | 3.2% | ✅ |
8PSK | 8 | 6.6 M | 6.30 × 10⁻⁵ vs 6.34 × 10⁻⁵ at 12 dB | 6.3% | ✅ |
16QAM | 8 | 5.5 M | 1.55 × 10⁻⁴ vs 1.39 × 10⁻⁴ at 12 dB | 11.5% | ✅ |
64QAM | 9 | 4.9 M | 2.23 × 10⁻⁴ vs 2.17 × 10⁻⁴ at 16 dB | 6.9% | ✅ |
256QAM | 7 | 5.6 M | 1.37 × 10⁻⁴ vs 1.35 × 10⁻⁴ at 21 dB | 11.8% | ✅ |
Theory with Gray mapping, $\gamma_b = E_b/N_0$, $k = \log_2 M$:
$$P_b^{\text{BPSK, QPSK}} = Q\big(\sqrt{2\gamma_b}\big),\qquad P_b^{M\text{-PSK}} \approx \tfrac{2}{k},Q\big(\sqrt{2k\gamma_b},\sin\tfrac{\pi}{M}\big),\qquad P_b^{M\text{-QAM}} \approx \tfrac{4}{k}\big(1-\tfrac{1}{\sqrt M}\big),Q\Big(\sqrt{\tfrac{3k\gamma_b}{M-1}}\Big)$$
The QAM and PSK expressions are the standard nearest-neighbour approximations, which is why the largest deviations (about 10%) appear at low SNR for the dense constellations, where errors to non-adjacent points start to matter.
Rayleigh fading
Every expression above has the form $c,Q(\sqrt{a\gamma_b})$. Averaging over a Rayleigh channel, where $|h|^2$ is exponential, gives an exact closed form:
$$\mathbb E\Big[c,Q\big(\sqrt{a\gamma_b |h|^2}\big)\Big] = \frac{c}{2}\left(1-\sqrt{\frac{a\gamma_b}{2+a\gamma_b}}\right)$$
Eb/N0 (dB) | BPSK simulated | BPSK theory | 16-QAM simulated | 16-QAM theory |
0 | 1.45 × 10⁻¹ | 1.46 × 10⁻¹ | 1.97 × 10⁻¹ | 1.75 × 10⁻¹ |
5 | 6.38 × 10⁻² | 6.42 × 10⁻² | 1.02 × 10⁻¹ | 9.48 × 10⁻² |
10 | 2.33 × 10⁻² | 2.33 × 10⁻² | 4.26 × 10⁻² | 3.96 × 10⁻² |
15 | 8.03 × 10⁻³ | 7.72 × 10⁻³ | 1.52 × 10⁻² | 1.40 × 10⁻² |
20 | 2.54 × 10⁻³ | 2.48 × 10⁻³ | 4.66 × 10⁻³ | 4.60 × 10⁻³ |
25 | 7.86 × 10⁻⁴ | 7.89 × 10⁻⁴ | 1.60 × 10⁻³ | 1.47 × 10⁻³ |
30 | 2.42 × 10⁻⁴ | 2.50 × 10⁻⁴ | 5.05 × 10⁻⁴ | 4.68 × 10⁻⁴ |
Fading turns the waterfall into a straight line: every 10 dB of extra power buys only one decade of BER, instead of many. That is the case for diversity and coding in one plot.
OFDM: what LS channel estimation costs
SNR (dB) | BER, perfect channel | BER, LS + interpolation | Channel NMSE, LS |
0 | 2.10 × 10⁻¹ | 2.85 × 10⁻¹ | -1.7 dB |
6 | 9.53 × 10⁻² | 1.41 × 10⁻¹ | -7.6 dB |
12 | 2.76 × 10⁻² | 4.66 × 10⁻² | -13.1 dB |
18 | 3.40 × 10⁻³ | 6.86 × 10⁻³ | -17.8 dB |
24 | 5.21 × 10⁻⁵ | 2.08 × 10⁻⁴ | -20.6 dB |
30 | 0 | 0 | -21.7 dB |
64 subcarriers, cyclic prefix 16, a pilot on every 4th subcarrier, a 6-tap channel with 3 dB/tap decay, QPSK, 600 OFDM symbols (57,600 data bits) per point. LS costs about 2 to 3 dB. Notice the NMSE column: it improves with SNR and then stops near −22 dB. That floor is not noise; it is the error of linear interpolation between pilots on a frequency-selective channel, and it is exactly the gap that MMSE and neural-network estimators try to close.
Peak-to-average power ratio of the OFDM symbols: mean 8.9 dB, and 1% of symbols exceed 11.6 dB, the reason OFDM transmitters need power amplifier back-off.
Pulse shaping: bandwidth vs roll-off
Roll-off β | 0 | 0.15 | 0.25 | 0.35 | 0.5 | 0.75 | 1 |
99% bandwidth / symbol rate | 1.00 | 1.05 | 1.10 | 1.16 | 1.27 | 1.45 | 1.63 |
The Nyquist bandwidth $(1+\beta)R_s$ contains all the energy, but 99% of it sits in a noticeably narrower band, because the raised-cosine roll-off region carries little power.
🔬 Real tool outputs
Every image below was returned by the server over the MCP protocol during validation, with the JSON it sent alongside.
// rf_link_budget() → 20 dBm, 2 dBi + 2 dBi, 2.4 GHz, 100 m, 20 MHz, NF 7 dB
{"fspl_db": 80.054, "pr_dbm": -56.054, "noise_dbm": -93.99, "snr_db": 37.935, "capacity_mbps": 252.042}Speed
Tool | Round trip through MCP (laptop-class CPU) |
| 384 ms |
| 108 ms |
| 209 ms |
| 277 ms |
| 156 ms |
| 35 ms |
| 2 ms |
Fast enough that Claude can call several tools in one answer without you noticing.
🗂️ Inside
mcp-signal-lab/
├── signallab/
│ ├── dsp.py constellations, channels, BER theory, Monte Carlo, OFDM, RRC, link budgets
│ ├── plots.py oscilloscope-style figures
│ ├── server.py the 7 MCP tools
│ └── __main__.py python -m signallab (stdio transport)
├── scripts/
│ ├── validate.py calibration against theory + timed MCP round trips
│ └── make_media.py the two animated GIFs, from real simulations
├── tests/ 20 tests: DSP correctness and MCP protocol calls
├── results/ validation.json and every figure above
└── assets/ animated SVG header and GIFspip install -e ".[test]"
python -m pytest -q # 20 passed
python scripts/validate.py # ~10 s, rewrites results/
python scripts/make_media.py⚠️ Limits
Baseband, discrete-time simulations: no carrier frequency offset, timing recovery or amplifier non-linearity.
Rayleigh results assume perfect channel knowledge; OFDM uses a static channel per run.
BER points stop after 200 errors or the bit cap, so very low BERs carry wide confidence intervals; the bit count is always reported.
The M-PSK and M-QAM theory curves are approximations (exact for BPSK and QPSK).
📚 References
J. G. Proakis and M. Salehi, Digital Communications, 5th ed., McGraw-Hill, 2008.
A. Goldsmith, Wireless Communications, Cambridge University Press, 2005 (fading BER, Ch. 6).
J. M. Kahn and J. R. Barry, "Wireless infrared communications," Proc. IEEE, 85(2), 1997 (VLC gain).
Model Context Protocol specification: modelcontextprotocol.io
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
This server cannot be deployed
Maintenance
Related MCP Connectors
Create RF signal projects from prompts, inspect graphs, and export IQ data.
AI Visibility and Content Intelligence tools for Claude and MCP-compatible agents.
Use AI models for chat, image, and video generation from Claude Code and other MCP hosts.
Build, run and analyse block-diagram simulations: PID, Bode, FFT, optimisation and code export.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables Claude Code to control Ansys engineering simulations (CFD, FEA, meshing, post-processing) through natural language commands via PyAnsys.15MIT
- AlicenseAqualityBmaintenanceEnables AI agents to validate wireless communication ideas by providing standardized channel instances and physical measurements through MCP, eliminating the need to write simulations from scratch.283MIT
- AlicenseNot gradedqualityCmaintenanceEnables agents to conduct evidence-driven communication experiments (BPSK/QPSK + AWGN) through Sionna-based probes, statistical verification, and controlled diagnosis via MCP tools.Apache 2.0
- AlicenseNot gradedqualityBmaintenanceEnables Claude to open, build, edit, solve, and report on DWSIM 9.0.5 process simulations, either live in a DWSIM window or in a hidden background copy.MIT