Analog Discovery MCP Server
Python MCP server for Digilent Analog Discovery 2 and Analog Discovery 3.
This project exposes a small local instrument-control tool surface for MCP clients:
- Detect the installed Digilent WaveForms SDK version.
- List connected WaveForms-compatible devices.
- Read one analog input voltage sample from channel 1 or 2.
- Capture analog input waveforms with optional analog edge triggers.
- Measure core voltage statistics from one analog input channel.
- Drive Wavegen outputs: sine, square, triangle, DC, and bounded custom samples.
- Read and drive static digital I/O pins.
- Safely release active outputs and the WaveForms device handle.
Analog waveform capture is supported for small local captures.
Requirements
- Python 3.11 or newer
- uv for local development
- Digilent WaveForms installed on the machine that runs the MCP server
WaveForms includes the WaveForms SDK dynamic library used by this server:
- Windows:
dwf - macOS:
/Library/Frameworks/dwf.framework/dwf - Linux:
libdwf.so
Install From PyPI
Run directly with uvx:
uvx analog-discovery-mcp-server
Or install into an environment:
pip install analog-discovery-mcp-server
analog-discovery-mcp-server
The server uses MCP stdio transport. Your MCP client starts this process and talks to it over standard input/output; no port or web server is opened.
Install From Source
For local development from a clone of this repository:
uv sync
uv run analog-discovery-mcp-server
Run Without Hardware
Use the fake backend to test MCP client wiring when no Analog Discovery device is connected:
AD_MCP_DWF_BACKEND=fake uvx analog-discovery-mcp-server
The fake backend is deterministic and for demos only. It reports one fake Analog Discovery 3 device, fixed voltage readings for channels 1 and 2, and simulated waveform capture payloads for client prototyping. It also simulates Wavegen output state and static digital I/O state for tests.
MCP Client Configuration
Example local configuration:
{
"mcpServers": {
"analog-discovery": {
"command": "uvx",
"args": [
"analog-discovery-mcp-server"
]
}
}
}
Development configuration from a source checkout:
{
"mcpServers": {
"analog-discovery-dev": {
"command": "uv",
"args": [
"--directory",
"/path/to/analog-discovery-mcp-server",
"run",
"analog-discovery-mcp-server"
]
}
}
}
Device Selection
Tools can select a device using either device_index or serial_number.
You can also set defaults:
export AD_MCP_DEVICE_INDEX=0
export AD_MCP_DEVICE_SERIAL=SN:210415BD66A3
Set only one default at a time. Explicit tool arguments override environment defaults.
Tools
These tools are available through MCP for both real WaveForms hardware and the fake backend.
Device And SDK
get_waveforms_version
Returns the detected WaveForms SDK version.
list_devices
Returns connected devices with index, name, serial number, and availability.
Analog Input
read_analog_voltage
Reads one analog input voltage sample.
Inputs:
channel:1or2device_index: optional zero-based device indexserial_number: optional device serial number
get_analog_capture_limits
Returns analog waveform capture limits for the selected device.
The fake backend reports AD3-like limits: 32,768 samples per channel and 65,536 total returned samples. The real backend reports supported analog input channels and WaveForms buffer limits, with a conservative total returned sample limit.
capture_analog_waveform
Returns analog input waveform samples for the selected channel or channels.
Inputs:
channels: optional list containing1,2, or both; default[1]sample_rate_hz: positive sample rate; default1000.0sample_count: samples per channel; default1000device_index: optional zero-based device indexserial_number: optional device serial numbertrigger_enabled: optional analog edge trigger enable; defaultfalsetrigger_channel: optional trigger channel; defaults to first requested channeltrigger_level_v: trigger level in volts; default0.0trigger_edge:risingorfalling; defaultrisingtrigger_hysteresis_v: trigger hysteresis in volts; default0.05trigger_auto_timeout_seconds: auto-trigger timeout; default1.0trigger_position_seconds: trigger position in capture window; default half duration
The server rejects requests above reported capture limits. It does not silently truncate or clamp sample arrays.
The response includes sample arrays plus metadata such as actual sample rate, trigger state, valid sample count, lost/corrupt sample counts, and WaveForms status time when available.
measure_analog_waveform
Captures one analog input channel and returns core voltage statistics without raw sample arrays.
Inputs match capture_analog_waveform for one channel. If a trigger is enabled,
trigger_channel must be the measured channel or omitted. To measure channel
2 while triggering from channel 1, use capture_analog_waveform with
channels: [1, 2] and compute statistics from the returned samples.
Outputs include:
min_voltagemax_voltagemean_voltagerms_voltagepeak_to_peak_voltage- capture metadata such as actual sample rate, duration, trigger state, and device
get_analog_input_status
Returns AnalogIn capability and status metadata for the selected device.
Outputs include channel count, frequency limits, buffer limits, current frequency and buffer size, per-channel range/offset, and current AnalogIn state when available.
Wavegen Output
get_wavegen_limits
Returns Wavegen output channels, supported waveforms, defaults, and per-channel limits.
start_wavegen
Starts Wavegen output on one analog output channel.
Inputs:
channel: output channel, usually1or2; default1waveform:sine,square,triangle,dc, orcustom; defaultsinefrequency_hz: output frequency for non-DC waveforms; default1000.0amplitude_v: peak amplitude for non-DC waveforms; default1.0offset_v: voltage offset, or DC output voltage fordc; default0.0duty_cycle_percent: symmetry/duty cycle; default50.0samples: normalizedcustomwaveform samples, each between-1.0and1.0sample_rate_hz: playback sample rate forcustom; required withsamplesdevice_index: optional zero-based device indexserial_number: optional device serial number
For dc, the server uses offset_v as the output voltage and returns an effective
amplitude_v of 0.0.
For custom, samples defines one repeated cycle. The server converts
sample_rate_hz / len(samples) into the WaveForms cycle frequency and validates the
sample count against get_wavegen_limits.
Example custom waveform:
{
"waveform": "custom",
"samples": [-1.0, 0.0, 1.0, 0.0],
"sample_rate_hz": 4000.0,
"amplitude_v": 1.0,
"offset_v": 0.0
}
start_synchronized_wavegen
Starts multiple Wavegen output channels with hardware synchronization.
Inputs:
channels: output channels; default[1, 2]waveforms: one waveform per channel; supportssine,square,triangle, anddcfrequencies_hz: one frequency per channel; default1000.0amplitudes_v: one peak amplitude per channel; default1.0offsets_v: one voltage offset per channel; default0.0duty_cycles_percent: one symmetry/duty cycle per channel; default50.0phase_degrees: one phase per channel; default[0.0, 180.0]for two channelsmaster_channel: channel that starts the synchronized group; default1device_index: optional zero-based device indexserial_number: optional device serial number
All provided per-channel lists must have the same length as channels. The synchronized
tool uses WaveForms master/slave hardware control and phase settings; custom waveforms
are not supported by this tool.
Example synchronized opposite-phase sine:
{
"channels": [1, 2],
"waveforms": ["sine", "sine"],
"frequencies_hz": [1000.0, 1000.0],
"amplitudes_v": [2.0, 2.0],
"offsets_v": [0.0, 0.0],
"phase_degrees": [0.0, 180.0],
"master_channel": 1
}
stop_wavegen
Stops Wavegen output on one channel. The fake backend preserves the last config in status.
get_wavegen_status
Returns Wavegen state, running flag, and current config when available.
release_device
Safely releases MCP ownership of the selected device. This stops active Wavegen channels tracked by the server, disables static DIO outputs, and closes the cached WaveForms device handle so other applications can open the hardware.
Inputs:
device_index: optional zero-based device indexserial_number: optional device serial number
Outputs include released, wavegen_channels_stopped,
digital_output_enable_mask, and device.
Digital I/O
Digital pin numbers are zero-based and match WaveForms labels: public pin 0 is DIO0.
get_digital_io_limits
Returns static digital I/O pin capabilities for the selected device.
Outputs include:
supported_input_pinssupported_output_pinsinput_maskoutput_enable_maskdevice
read_digital_inputs
Reads static digital input pin values.
Inputs:
pins: optional list of zero-based DIO pins; default reads all supported input pinsdevice_index: optional zero-based device indexserial_number: optional device serial number
Outputs include selected pins, string-keyed boolean values, raw input_mask, and device.
write_digital_outputs
Writes static digital output pin values.
Inputs:
pins: list of zero-based output pinsvalues: same-length list of booleanspreserve_existing: keep unselected output state when true; defaulttruedevice_index: optional zero-based device indexserial_number: optional device serial number
Outputs include selected pins, string-keyed boolean values, output_enable_mask,
output_mask, and device.
Development
uv sync
uv run ruff check
uv run mypy
uv run pytest -q
uv build
Test the MCP server without hardware:
AD_MCP_DWF_BACKEND=fake uv run analog-discovery-mcp-server
Hardware integration tests are skipped by default. Enable them explicitly:
AD_MCP_HARDWARE_TESTS=1 uv run pytest -m hardware
Hardware tests can also select a documented physical stand:
AD_MCP_HARDWARE_TESTS=1 AD_MCP_HARDWARE_STAND=advanced uv run pytest -m hardware -q
Available stands are documented in docs/HARDWARE_TESTING.md. External real MCP client/agent validation scenarios are documented in docs/REAL_AGENT_VALIDATION.md.
The staged development plan lives in docs/ROADMAP.md.
AI Assistance
This project was created and developed with help from AI coding agents. Human maintainers review, test, and maintain accepted changes, and remain responsible for correctness, licensing, safety, and releases.
AI tools are not authors or copyright holders for this project.
Safety
Wavegen and digital output tools drive hardware outputs. Verify wiring, voltage range, load, and common ground before starting output.
Reading and capturing analog input still opens and configures the selected WaveForms device as required by the SDK. Check input voltage limits before connecting any circuit to Analog Discovery hardware.
Metadata
Release files for analog-discovery-mcp-server 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| analog_discovery_mcp_server-0.2.0.tar.gz | 122.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| analog_discovery_mcp_server-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 149.1 kB
Release files / analog_discovery_mcp_server-0.2.0.tar.gz
| Download URL | analog_discovery_mcp_server-0.2.0.tar.gz |
|---|---|
| Size | 122.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
afc4e88dd6fd4d80418aff83053981e87d1352b8dfe47b02f5cc7d85ce7bb7e7
|
|
BLAKE2b-256 checksum How to use checksums |
d54481cb33c13e179ce855e0e1fc4a1320610a6ab472ad850dd3f9dd9c413b24
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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 Jun 24, 2026.
Transparency logRelease files / analog_discovery_mcp_server-0.2.0-py3-none-any.whl
| Download URL | analog_discovery_mcp_server-0.2.0-py3-none-any.whl |
|---|---|
| Size | 26.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
81091abff6dccaaf80ca6d4d992340f0ba3b20157a0db3b82fb45c3d31e0b078
|
|
BLAKE2b-256 checksum How to use checksums |
35748e6c923c6311c63ed70c9c5f79ec7281a28fe551d150591cf47362eb4006
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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 Jun 24, 2026.
Transparency log