rigol-dg900-mcp
MCP server that lets an AI assistant drive a RIGOL DG800 Pro / DG900 Pro arbitrary waveform generator over LAN (raw SCPI on TCP 5555), with tools for setting waveforms, output loads, and reading status.
README
rigol-dg900-mcp
An MCP server that lets an AI assistant drive a RIGOL DG800 Pro / DG900 Pro function / arbitrary waveform generator over LAN (raw SCPI on TCP 5555).
This is a signal source, not an oscilloscope
The DG800/DG900 family generates waveforms. It cannot measure a signal, capture it, or display it. If you are looking for a way to look at a waveform, this is the wrong instrument and the wrong repository — you want a scope (Rigol's DS/MSO lines).
The one measuring feature it does have is a frequency counter on a separate input (
dg_counter), and that only reports frequency / period / duty of a periodic signal. It will not tell you anything useful about, say, serial data.The
DGprefix is easy to mistake for a scope model. It is not one.
*IDN? -> RIGOL TECHNOLOGIES,DG902 Pro,DG9P281200133,...
Why LAN and not USB
The DG900 Pro exposes both USB (USB-TMC) and LAN. On Windows the USB path needs a
USB-TMC driver bound to the device — without one it sits at CM_PROB_FAILED_INSTALL
and neither libusb nor PyVISA can see it. Binding WinUSB means Zadig, admin rights and
a system change.
LAN needs none of that: it is a plain TCP socket carrying SCPI lines. No driver, no admin, no vendor runtime. That is the only transport this server implements.
To find the address: on the instrument, Utility → I/O → LAN.
Tools
| Tool | What it does |
|---|---|
dg_set_host(host, port) |
Register the instrument's IP. Verifies *IDN? and stores it. |
dg_status |
Model, per-channel waveform, output state, output load. Read only. |
dg_set_load(ch, ohms) |
Output impedance. "INF" for high-Z. Read the gotcha below. |
dg_apply(ch, shape, freq, vpp, offset, phase) |
Set the waveform. Does not enable the output. |
dg_logic_pulse(ch, freq, high_v, duty) |
Safe helper: 0 V → high_v square wave, forces high-Z first. |
dg_output_on(ch) |
Actually emits a signal. |
dg_output_off(ch) |
Turns the output off. ch=0 for both. |
dg_counter(enable, seconds) |
Built-in frequency counter. |
dg_query(command) |
Arbitrary SCPI query (must end in ?). Read only. |
Safety design
dg_applynever turns the output on. You set values first, then energise — in that order.- Anything above 10 Vpp is rejected before it reaches the instrument.
- Above 5 Vpp you must pass
expect_vppmatching the value, so a leftover setting from earlier work cannot be emitted by accident. dg_output_onre-reads the instrument's current setting, not the conversation's, and refuses if it exceeds 5 Vpp without confirmation.dg_queryrefuses anything that is not a query.- The socket is opened and closed per call, so a long call cannot block "turn the output off".
This does not replace a physical means of disconnecting the instrument.
The gotcha that will destroy something
Output impedance defaults to 50 Ω, and the instrument compensates for it.
The generator sets its internal source so that the configured load sees the amplitude you asked for. Ask for 3.3 Vpp with the load set to 50 Ω, then connect a high-impedance input — a microcontroller pin, a scope probe, a logic input — and the pin actually sees 6.6 Vpp.
That is how you put 6.6 V into a 3.3 V pin.
Always set the load to high impedance before driving logic:
dg_set_load(1, "INF")
dg_status and dg_apply both warn when the load is still 50 Ω, and print what the real
amplitude would be. dg_logic_pulse forces high-Z before it sets anything, which is why it
exists.
Requirements
- Python 3.10+
mcp(the official Python SDK;FastMCPships inside it)
No PyVISA, no libusb, no vendor runtime. Only the standard library plus mcp.
pip install mcp
Install
claude mcp add --scope user dg900 -- python /path/to/server.py
Then restart your client so the tools appear.
Set the address once:
dg_set_host("192.168.1.50")
It is stored in state.json next to the server. DG_HOST / DG_PORT environment
variables take precedence if set.
SCPI used
From the official RIGOL programming guide (DG800 Pro/DG900 Pro Programming Guide):
| Command | Meaning |
|---|---|
*IDN? |
Identify |
[:SOURce[<n>]]:APPLy:{SINusoid|SQUare|RAMP|PULSe|NOISe|DC} <freq>,<amp>,<offset>,<phase> |
Set waveform |
[:SOURce[<n>]]:APPLy? |
Query waveform |
:OUTPut[<n>][:STATe] <state> |
Output on/off |
:OUTPut[<n>]:LOAD {<ohms>|INFinity} |
Output impedance |
[:SOURce[<n>]]:FUNCtion:SQUare:DCYCle <percent> |
Square duty cycle |
:COUNter[:STATe] <bool> |
Frequency counter on/off |
:COUNter:MEASure:{FREQuency|PERiod|DUTYcycle}? |
Counter readings |
Status
Written against the official programming guide. The LAN transport and the tool logic have not yet been exercised against the instrument — the unit this was written for was connected by USB only. Verified behaviour will be recorded here once it has been run on hardware.
日本語
RIGOL DG800 Pro / DG900 Pro(任意波形発生器)を LAN 経由(SCPI over TCP、5555番) で 操作するための MCP サーバーです。
これは信号を「出す」機械です。オシロスコープではありません
DG800/DG900 系は波形を作って出す機械です。信号を測ることも、取り込むことも、 画面に出すこともできません。波形を見たいのなら、機種もこのリポジトリも違います (見るための機械は Rigol なら DS / MSO 系)。
唯一の測る機能は、別の端子に付いている周波数計(
dg_counter)だけです。 しかもこれは繰り返しのある信号の周波数・周期・デューティしか出しません。 通信のデータのような、繰り返しでない信号を測っても意味のある値は出ません。
DGという型名はオシロの型番と取り違えやすいので、念のため書いておきます。
なぜ USB ではなく LAN か
この機種は USB と LAN の両方を持っています。ただし Windows で USB を使うには
USB-TMC のドライバを機器に割り当てる作業が要ります。割り当てないと機器は
CM_PROB_FAILED_INSTALL のまま止まり、libusb からも PyVISA からも見えません。
割り当てには Zadig のような道具と管理者権限、つまり環境を変える作業が要ります。
LAN なら何も要りません。ただの TCP の口に SCPI の文字列を流すだけです。 ドライバも管理者権限もメーカー製の常駐ソフトも不要。この実装は LAN だけを使います。
アドレスの調べ方: 機器の画面で Utility → I/O → LAN。
道具
| 道具 | 内容 |
|---|---|
dg_set_host(host, port) |
接続先の IP を登録する。*IDN? で相手を確かめてから保存する |
dg_status |
機種・各チャンネルの波形・出力の入切・負荷。読むだけ |
dg_set_load(ch, ohms) |
出力インピーダンス。"INF" で高インピーダンス。下の落とし穴を読むこと |
dg_apply(ch, shape, freq, vpp, offset, phase) |
波形を決める。出力は入れない |
dg_logic_pulse(ch, freq, high_v, duty) |
0V〜指定電圧の方形波。先に高インピーダンスへ強制する安全版 |
dg_output_on(ch) |
実際に信号が出る |
dg_output_off(ch) |
出力を切る。ch=0 で両方 |
dg_counter(enable, seconds) |
内蔵の周波数計で測る |
dg_query(command) |
任意の SCPI の問い合わせ(末尾が ? のものだけ)。読むだけ |
安全のきまり
dg_applyは出力を入れない。値を決めてから入れる、という順序を守れる- 10Vpp を超える指示は、機器に送る前に断る
- 5Vpp を超えるときは
expect_vppに同じ値を渡さないと実行しない。 前の作業の設定が残っていて、意図しない振幅が出る事故を防ぐ dg_output_onは会話の値ではなく機器に入っている設定を読み直して判断するdg_queryは問い合わせ以外を受け付けない- 接続は呼び出しごとに開閉する。長く握って「出力を切る」が待たされる事態を作らない
これは機器を物理的に切り離す手段の代わりにはなりません。
何かを壊す落とし穴
出力インピーダンスの初期値は 50Ω で、機器はそれを見込んだ電圧を出します。
機器は「設定した負荷につないだときに指示どおりの振幅になる」ように出力します。 負荷が 50Ω のまま 3.3Vpp を指示して、入力インピーダンスの高い相手 (マイコンの足、計測器の入口、論理回路の入力)につなぐと、 相手には 6.6Vpp が届きます。
3.3V の足に 6.6V を入れる、というのはこうして起きます。
論理回路を叩く前に、必ず高インピーダンスにしてください。
dg_set_load(1, "INF")
dg_status と dg_apply は、負荷が 50Ω のままなら実際に出る振幅を添えて警告します。
dg_logic_pulse が存在するのは、この事故を構造的に防ぐためです
(設定の前に高インピーダンスへ強制する)。
必要なもの
- Python 3.10 以上
mcp(公式の Python SDK。FastMCPはこの中に入っている)
PyVISA も libusb もメーカーの常駐ソフトも要りません。標準ライブラリと mcp だけです。
使えるようにする
claude mcp add --scope user dg900 -- python /path/to/server.py
登録したら、道具が現れるように利用側を起動し直します。アドレスは一度登録すれば残ります。
dg_set_host("192.168.1.50")
state.json に保存されます。環境変数 DG_HOST / DG_PORT があればそちらが優先されます。
いまの状態
公式のプログラミングガイドに沿って書きましたが、実機での動作確認はまだです。 書いた時点で手元の個体は USB でしか繋がっておらず、LAN の口を使えませんでした。 実機で確かめたことは、確かめ次第ここに書き足します。
ライセンス
MIT
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
E2B
Using MCP to run code via e2b.
Neon Database
MCP server for interacting with Neon Management API and databases
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.