siglent-sdg-mcp 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +467 -0
- package/build/connection.d.ts +29 -0
- package/build/connection.js +252 -0
- package/build/index.d.ts +2 -0
- package/build/index.js +52 -0
- package/build/tools/arbitrary.d.ts +2 -0
- package/build/tools/arbitrary.js +83 -0
- package/build/tools/basic-wave.d.ts +2 -0
- package/build/tools/basic-wave.js +172 -0
- package/build/tools/burst.d.ts +2 -0
- package/build/tools/burst.js +191 -0
- package/build/tools/connection.d.ts +2 -0
- package/build/tools/connection.js +90 -0
- package/build/tools/modulation.d.ts +2 -0
- package/build/tools/modulation.js +200 -0
- package/build/tools/output.d.ts +2 -0
- package/build/tools/output.js +87 -0
- package/build/tools/scpi.d.ts +2 -0
- package/build/tools/scpi.js +65 -0
- package/build/tools/sweep.d.ts +2 -0
- package/build/tools/sweep.js +221 -0
- package/build/tools/utility.d.ts +2 -0
- package/build/tools/utility.js +126 -0
- package/package.json +49 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Magnus Johansson
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,467 @@
|
|
|
1
|
+
# siglent-sdg-mcp
|
|
2
|
+
|
|
3
|
+
A [Model Context Protocol](https://modelcontextprotocol.io/) (MCP) server that lets AI assistants control Siglent SDG waveform generators over your local network. Connect Claude to your bench and generate, modulate, and configure signals through natural language.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
This MCP server communicates with Siglent SDG waveform generators via SCPI commands over TCP sockets (port 5025). No VISA drivers or NI-MAX installation required — just a network connection to your generator.
|
|
8
|
+
|
|
9
|
+
**Key features:**
|
|
10
|
+
|
|
11
|
+
- 21 tools covering output control, waveform generation, modulation, sweep, burst, arbitrary waveforms, and more
|
|
12
|
+
- Dual-channel support (C1 and C2)
|
|
13
|
+
- 8 waveform types: sine, square, ramp, pulse, noise, arbitrary, DC, PRBS
|
|
14
|
+
- 8 modulation types: AM, DSB-AM, FM, PM, PWM, ASK, FSK, PSK
|
|
15
|
+
- Auto-connect on startup via environment variable
|
|
16
|
+
- Query queue serializes commands automatically — tools can safely run in parallel
|
|
17
|
+
- Raw SCPI escape hatch for any command not covered by the built-in tools
|
|
18
|
+
|
|
19
|
+
## Compatibility
|
|
20
|
+
|
|
21
|
+
| Status | Model |
|
|
22
|
+
|--------|-------|
|
|
23
|
+
| Tested | SDG1032X |
|
|
24
|
+
| Expected to work | SDG1000X series (SDG1062X, etc.) |
|
|
25
|
+
| May work | Other Siglent SDG models with SCPI over TCP support |
|
|
26
|
+
|
|
27
|
+
The server uses standard SCPI commands from the SDG series programming guide. Other Siglent models that support the same command set over port 5025 should work with little or no modification.
|
|
28
|
+
|
|
29
|
+
## Quick Start
|
|
30
|
+
|
|
31
|
+
You need a Siglent waveform generator accessible on your network (TCP port 5025). Pick one of the three options below and add the config to your `.mcp.json` (in your project directory, or `~/.claude/.mcp.json` for global access).
|
|
32
|
+
|
|
33
|
+
Replace `192.168.1.126` with your generator's IP address.
|
|
34
|
+
|
|
35
|
+
### Option A: Docker (recommended)
|
|
36
|
+
|
|
37
|
+
No Node.js installation required. Works on Linux, macOS, and Windows (via WSL2 or Docker Desktop).
|
|
38
|
+
|
|
39
|
+
```json
|
|
40
|
+
{
|
|
41
|
+
"mcpServers": {
|
|
42
|
+
"siglent-sdg": {
|
|
43
|
+
"type": "stdio",
|
|
44
|
+
"command": "docker",
|
|
45
|
+
"args": [
|
|
46
|
+
"run", "--rm", "-i",
|
|
47
|
+
"-e", "SIGLENT_SDG_IP=192.168.1.126",
|
|
48
|
+
"ghcr.io/magnusjohansson/siglent-sdg-mcp:latest"
|
|
49
|
+
]
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Option B: npx
|
|
56
|
+
|
|
57
|
+
Requires Node.js 20+. Downloads and runs the package automatically.
|
|
58
|
+
|
|
59
|
+
```json
|
|
60
|
+
{
|
|
61
|
+
"mcpServers": {
|
|
62
|
+
"siglent-sdg": {
|
|
63
|
+
"type": "stdio",
|
|
64
|
+
"command": "npx",
|
|
65
|
+
"args": ["-y", "siglent-sdg-mcp"],
|
|
66
|
+
"env": {
|
|
67
|
+
"SIGLENT_SDG_IP": "192.168.1.126"
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Option C: Clone and build
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
git clone https://github.com/magnusjohansson/siglent-sdg-mcp.git
|
|
78
|
+
cd siglent-sdg-mcp
|
|
79
|
+
npm install
|
|
80
|
+
npm run build
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
```json
|
|
84
|
+
{
|
|
85
|
+
"mcpServers": {
|
|
86
|
+
"siglent-sdg": {
|
|
87
|
+
"type": "stdio",
|
|
88
|
+
"command": "node",
|
|
89
|
+
"args": ["/path/to/siglent-sdg-mcp/build/index.js"],
|
|
90
|
+
"env": {
|
|
91
|
+
"SIGLENT_SDG_IP": "192.168.1.126"
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Replace `/path/to/siglent-sdg-mcp` with the actual path to your clone.
|
|
99
|
+
|
|
100
|
+
### Environment Variables
|
|
101
|
+
|
|
102
|
+
| Variable | Required | Default | Description |
|
|
103
|
+
|----------|----------|---------|-------------|
|
|
104
|
+
| `SIGLENT_SDG_IP` | No | — | Generator IP address for auto-connect on startup |
|
|
105
|
+
| `SIGLENT_IP` | No | — | Fallback if `SIGLENT_SDG_IP` is not set |
|
|
106
|
+
| `SIGLENT_SDG_PORT` | No | `5025` | TCP port (only change if your setup differs) |
|
|
107
|
+
| `SIGLENT_PORT` | No | `5025` | Fallback if `SIGLENT_SDG_PORT` is not set |
|
|
108
|
+
|
|
109
|
+
### Auto-Connect Behavior
|
|
110
|
+
|
|
111
|
+
If `SIGLENT_SDG_IP` (or `SIGLENT_IP`) is set, the server attempts to connect to the generator immediately after starting. This runs in the background and does **not** block the MCP server — Claude can start using other tools right away. If the generator is offline or unreachable, the server logs a warning and you can connect manually later using the `connect` tool.
|
|
112
|
+
|
|
113
|
+
If neither variable is set, the server starts without a connection. Use the `connect` tool to connect when ready.
|
|
114
|
+
|
|
115
|
+
## Using with Other AI Clients
|
|
116
|
+
|
|
117
|
+
The Quick Start examples above use Claude Code's `.mcp.json` format, which includes a `"type": "stdio"` field. Other AI clients use the same JSON structure but **without** the `"type"` field and with different config file locations.
|
|
118
|
+
|
|
119
|
+
### Claude Desktop
|
|
120
|
+
|
|
121
|
+
Edit `claude_desktop_config.json`:
|
|
122
|
+
|
|
123
|
+
- **Windows:** `%APPDATA%\Claude\claude_desktop_config.json`
|
|
124
|
+
- **macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json`
|
|
125
|
+
|
|
126
|
+
#### Docker
|
|
127
|
+
|
|
128
|
+
```json
|
|
129
|
+
{
|
|
130
|
+
"mcpServers": {
|
|
131
|
+
"siglent-sdg": {
|
|
132
|
+
"command": "docker",
|
|
133
|
+
"args": [
|
|
134
|
+
"run", "--rm", "-i",
|
|
135
|
+
"-e", "SIGLENT_SDG_IP=192.168.1.126",
|
|
136
|
+
"ghcr.io/magnusjohansson/siglent-sdg-mcp:latest"
|
|
137
|
+
]
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
#### npx
|
|
144
|
+
|
|
145
|
+
```json
|
|
146
|
+
{
|
|
147
|
+
"mcpServers": {
|
|
148
|
+
"siglent-sdg": {
|
|
149
|
+
"command": "npx",
|
|
150
|
+
"args": ["-y", "siglent-sdg-mcp"],
|
|
151
|
+
"env": {
|
|
152
|
+
"SIGLENT_SDG_IP": "192.168.1.126"
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
> **Note:** You must fully restart Claude Desktop after changing the config file.
|
|
160
|
+
|
|
161
|
+
### Cursor
|
|
162
|
+
|
|
163
|
+
Edit one of:
|
|
164
|
+
|
|
165
|
+
- **User-level:** `~/.cursor/mcp.json` (available across all projects)
|
|
166
|
+
- **Project-level:** `.cursor/mcp.json` (shared with your team via version control)
|
|
167
|
+
|
|
168
|
+
You can also add servers through the UI: **Settings > Cursor Settings > MCP > Add new global MCP server**.
|
|
169
|
+
|
|
170
|
+
#### Docker
|
|
171
|
+
|
|
172
|
+
```json
|
|
173
|
+
{
|
|
174
|
+
"mcpServers": {
|
|
175
|
+
"siglent-sdg": {
|
|
176
|
+
"command": "docker",
|
|
177
|
+
"args": [
|
|
178
|
+
"run", "--rm", "-i",
|
|
179
|
+
"-e", "SIGLENT_SDG_IP=192.168.1.126",
|
|
180
|
+
"ghcr.io/magnusjohansson/siglent-sdg-mcp:latest"
|
|
181
|
+
]
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
#### npx
|
|
188
|
+
|
|
189
|
+
```json
|
|
190
|
+
{
|
|
191
|
+
"mcpServers": {
|
|
192
|
+
"siglent-sdg": {
|
|
193
|
+
"command": "npx",
|
|
194
|
+
"args": ["-y", "siglent-sdg-mcp"],
|
|
195
|
+
"env": {
|
|
196
|
+
"SIGLENT_SDG_IP": "192.168.1.126"
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### Windsurf
|
|
204
|
+
|
|
205
|
+
Edit `mcp_config.json`:
|
|
206
|
+
|
|
207
|
+
- **Windows:** `%USERPROFILE%\.codeium\windsurf\mcp_config.json`
|
|
208
|
+
- **macOS/Linux:** `~/.codeium/windsurf/mcp_config.json`
|
|
209
|
+
|
|
210
|
+
You can also configure servers through the UI: **Cascade panel > MCP icon > Manage MCP Servers > View raw config**.
|
|
211
|
+
|
|
212
|
+
#### Docker
|
|
213
|
+
|
|
214
|
+
```json
|
|
215
|
+
{
|
|
216
|
+
"mcpServers": {
|
|
217
|
+
"siglent-sdg": {
|
|
218
|
+
"command": "docker",
|
|
219
|
+
"args": [
|
|
220
|
+
"run", "--rm", "-i",
|
|
221
|
+
"-e", "SIGLENT_SDG_IP=192.168.1.126",
|
|
222
|
+
"ghcr.io/magnusjohansson/siglent-sdg-mcp:latest"
|
|
223
|
+
]
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
#### npx
|
|
230
|
+
|
|
231
|
+
```json
|
|
232
|
+
{
|
|
233
|
+
"mcpServers": {
|
|
234
|
+
"siglent-sdg": {
|
|
235
|
+
"command": "npx",
|
|
236
|
+
"args": ["-y", "siglent-sdg-mcp"],
|
|
237
|
+
"env": {
|
|
238
|
+
"SIGLENT_SDG_IP": "192.168.1.126"
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
### Google Antigravity
|
|
246
|
+
|
|
247
|
+
Configuration is managed through the IDE's UI:
|
|
248
|
+
|
|
249
|
+
1. Open the **Agent pane** on the right side of the workspace
|
|
250
|
+
2. Click the **`...`** button at the top
|
|
251
|
+
3. Select **MCP Servers**
|
|
252
|
+
4. Click **Manage MCP Servers**
|
|
253
|
+
5. Click **View raw config**
|
|
254
|
+
6. Add the configuration below and save
|
|
255
|
+
|
|
256
|
+
#### Docker
|
|
257
|
+
|
|
258
|
+
```json
|
|
259
|
+
{
|
|
260
|
+
"mcpServers": {
|
|
261
|
+
"siglent-sdg": {
|
|
262
|
+
"command": "docker",
|
|
263
|
+
"args": [
|
|
264
|
+
"run", "--rm", "-i",
|
|
265
|
+
"-e", "SIGLENT_SDG_IP=192.168.1.126",
|
|
266
|
+
"ghcr.io/magnusjohansson/siglent-sdg-mcp:latest"
|
|
267
|
+
]
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
#### npx
|
|
274
|
+
|
|
275
|
+
```json
|
|
276
|
+
{
|
|
277
|
+
"mcpServers": {
|
|
278
|
+
"siglent-sdg": {
|
|
279
|
+
"command": "npx",
|
|
280
|
+
"args": ["-y", "siglent-sdg-mcp"],
|
|
281
|
+
"env": {
|
|
282
|
+
"SIGLENT_SDG_IP": "192.168.1.126"
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
Replace `192.168.1.126` with your generator's IP address in all examples above.
|
|
290
|
+
|
|
291
|
+
### ChatGPT Desktop
|
|
292
|
+
|
|
293
|
+
ChatGPT Desktop only supports remote HTTPS MCP servers (called "connectors"), not local stdio servers. Since this MCP server uses stdio transport, it is not directly compatible with ChatGPT Desktop.
|
|
294
|
+
|
|
295
|
+
## Tools
|
|
296
|
+
|
|
297
|
+
21 tools across 9 categories.
|
|
298
|
+
|
|
299
|
+
| Category | Tool | Description |
|
|
300
|
+
|----------|------|-------------|
|
|
301
|
+
| Connection | `connect` | Connect to waveform generator over TCP |
|
|
302
|
+
| | `disconnect` | Close the connection |
|
|
303
|
+
| | `identify` | Query device ID (manufacturer, model, serial, firmware) |
|
|
304
|
+
| Output | `get_output` | Read output state, load impedance, and polarity |
|
|
305
|
+
| | `configure_output` | Turn output on/off, set load impedance and polarity |
|
|
306
|
+
| Basic Waveform | `get_basic_wave` | Read waveform parameters (type, frequency, amplitude, etc.) |
|
|
307
|
+
| | `configure_basic_wave` | Set waveform type, frequency, amplitude, offset, phase, duty cycle, and more |
|
|
308
|
+
| Modulation | `get_modulation` | Read modulation settings (type, source, depth/deviation) |
|
|
309
|
+
| | `configure_modulation` | Set modulation type, source, frequency, depth, deviation, and carrier parameters |
|
|
310
|
+
| Sweep | `get_sweep` | Read sweep parameters (time, frequency range, mode, direction) |
|
|
311
|
+
| | `configure_sweep` | Set sweep time, start/stop frequencies, mode, direction, trigger, and marker |
|
|
312
|
+
| Burst | `get_burst` | Read burst parameters (mode, period, trigger, cycle count) |
|
|
313
|
+
| | `configure_burst` | Set burst mode, period, trigger source, cycle count, delay, and gate polarity |
|
|
314
|
+
| Arbitrary Waveform | `get_arbitrary_wave` | Read the current arbitrary waveform selection |
|
|
315
|
+
| | `set_arbitrary_wave` | Set arbitrary waveform by index (built-in) or name (user-defined) |
|
|
316
|
+
| Utility | `reset` | Reset generator to factory defaults (*RST) |
|
|
317
|
+
| | `copy_channel` | Copy all parameters from one channel to another |
|
|
318
|
+
| | `configure_sync` | Configure sync output signal |
|
|
319
|
+
| | `equal_phase` | Synchronize phase of both channels |
|
|
320
|
+
| SCPI | `scpi_query` | Send arbitrary SCPI query and return the response |
|
|
321
|
+
| | `scpi_command` | Send arbitrary SCPI command (no response expected) |
|
|
322
|
+
|
|
323
|
+
## Example Conversations
|
|
324
|
+
|
|
325
|
+
### Generate a basic waveform
|
|
326
|
+
|
|
327
|
+
> **You:** Output a 1 kHz sine wave at 2 Vpp on channel 1.
|
|
328
|
+
>
|
|
329
|
+
> Claude calls `configure_basic_wave` with `channel: "C1"`, `waveform_type: "SINE"`, `frequency: 1000`, `amplitude: 2`, then `configure_output` with `channel: "C1"`, `state: "ON"`.
|
|
330
|
+
|
|
331
|
+
### Set up modulation
|
|
332
|
+
|
|
333
|
+
> **You:** Add AM modulation to channel 1 with 80% depth at 100 Hz.
|
|
334
|
+
>
|
|
335
|
+
> Claude calls `configure_modulation` with `channel: "C1"`, `state: "ON"`, `type: "AM"`, `depth: 80`, `frequency: 100`.
|
|
336
|
+
|
|
337
|
+
### Configure a frequency sweep
|
|
338
|
+
|
|
339
|
+
> **You:** Sweep channel 2 from 100 Hz to 10 kHz over 5 seconds.
|
|
340
|
+
>
|
|
341
|
+
> Claude calls `configure_sweep` with `channel: "C2"`, `state: "ON"`, `start: 100`, `stop: 10000`, `time: 5`, then `configure_output` with `channel: "C2"`, `state: "ON"`.
|
|
342
|
+
|
|
343
|
+
### Check current settings
|
|
344
|
+
|
|
345
|
+
> **You:** What's the current waveform setup on both channels?
|
|
346
|
+
>
|
|
347
|
+
> Claude calls `get_basic_wave` on both C1 and C2 in parallel and reports the waveform type, frequency, amplitude, and other settings for each channel.
|
|
348
|
+
|
|
349
|
+
### Copy channel configuration
|
|
350
|
+
|
|
351
|
+
> **You:** Make channel 2 match channel 1's settings.
|
|
352
|
+
>
|
|
353
|
+
> Claude calls `copy_channel` with `source: "C1"`, `destination: "C2"`.
|
|
354
|
+
|
|
355
|
+
### Set up burst mode
|
|
356
|
+
|
|
357
|
+
> **You:** Configure channel 1 for 5-cycle bursts triggered externally.
|
|
358
|
+
>
|
|
359
|
+
> Claude calls `configure_burst` with `channel: "C1"`, `state: "ON"`, `burst_mode: "NCYC"`, `cycles: "5"`, `trigger_source: "EXT"`.
|
|
360
|
+
|
|
361
|
+
## Architecture
|
|
362
|
+
|
|
363
|
+
```
|
|
364
|
+
Claude Code <-- stdio/JSON-RPC --> siglent-sdg-mcp <-- TCP/SCPI --> Generator:5025
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
- **Transport:** MCP over stdio (JSON-RPC 2.0)
|
|
368
|
+
- **Protocol:** SCPI commands over raw TCP sockets, newline-terminated
|
|
369
|
+
- **Query Queue:** All SCPI queries are serialized through an internal queue. The generator processes one command at a time, so even when tools issue parallel requests, the queue ensures they're sent sequentially.
|
|
370
|
+
- **Auto-Connect:** If `SIGLENT_SDG_IP` is set, connects in the background on startup without blocking the MCP server.
|
|
371
|
+
|
|
372
|
+
## Development
|
|
373
|
+
|
|
374
|
+
```bash
|
|
375
|
+
npm run build # Compile TypeScript
|
|
376
|
+
npm run watch # Watch mode — recompile on changes
|
|
377
|
+
npm run dev # Build and run
|
|
378
|
+
npm run inspector # Launch with MCP Inspector for debugging
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
### Docker (local build)
|
|
382
|
+
|
|
383
|
+
Build the image locally:
|
|
384
|
+
|
|
385
|
+
```bash
|
|
386
|
+
docker build -t siglent-sdg-mcp .
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
Then use the local image in your `.mcp.json`:
|
|
390
|
+
|
|
391
|
+
```json
|
|
392
|
+
{
|
|
393
|
+
"mcpServers": {
|
|
394
|
+
"siglent-sdg": {
|
|
395
|
+
"type": "stdio",
|
|
396
|
+
"command": "docker",
|
|
397
|
+
"args": [
|
|
398
|
+
"run", "--rm", "-i",
|
|
399
|
+
"-e", "SIGLENT_SDG_IP=192.168.1.126",
|
|
400
|
+
"siglent-sdg-mcp"
|
|
401
|
+
]
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
### Project Structure
|
|
408
|
+
|
|
409
|
+
```
|
|
410
|
+
src/
|
|
411
|
+
index.ts # Entry point, MCP server setup
|
|
412
|
+
connection.ts # TCP socket manager with query queue
|
|
413
|
+
tools/
|
|
414
|
+
connection.ts # connect, disconnect, identify
|
|
415
|
+
output.ts # get_output, configure_output
|
|
416
|
+
basic-wave.ts # get_basic_wave, configure_basic_wave
|
|
417
|
+
modulation.ts # get_modulation, configure_modulation
|
|
418
|
+
sweep.ts # get_sweep, configure_sweep
|
|
419
|
+
burst.ts # get_burst, configure_burst
|
|
420
|
+
arbitrary.ts # get_arbitrary_wave, set_arbitrary_wave
|
|
421
|
+
utility.ts # reset, copy_channel, configure_sync, equal_phase
|
|
422
|
+
scpi.ts # scpi_query, scpi_command
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
## Troubleshooting
|
|
426
|
+
|
|
427
|
+
### "Not connected to waveform generator"
|
|
428
|
+
|
|
429
|
+
The generator isn't connected yet. Either set `SIGLENT_SDG_IP` in your `.mcp.json` env for auto-connect, or use the `connect` tool manually.
|
|
430
|
+
|
|
431
|
+
### Connection timeout
|
|
432
|
+
|
|
433
|
+
- Verify the generator's IP address (check the generator's Utility > Interface menu)
|
|
434
|
+
- Ensure port 5025 is accessible (try `telnet <generator-ip> 5025` from your machine)
|
|
435
|
+
- Check that no firewall is blocking the connection
|
|
436
|
+
- The generator only accepts one TCP connection at a time — close any other SCPI clients
|
|
437
|
+
|
|
438
|
+
### Query timeout
|
|
439
|
+
|
|
440
|
+
Some SCPI queries can take a few seconds. The default timeout is 5 seconds. For `scpi_query`, you can increase the timeout with the `timeout_ms` parameter.
|
|
441
|
+
|
|
442
|
+
### Docker: can't reach the waveform generator
|
|
443
|
+
|
|
444
|
+
By default, Docker containers can reach LAN devices via the bridge network (NAT). If the container can't connect to your generator:
|
|
445
|
+
|
|
446
|
+
- Verify the generator is reachable from your host: `telnet 192.168.1.126 5025`
|
|
447
|
+
- On Linux, try adding `--network host` to the Docker args:
|
|
448
|
+
```json
|
|
449
|
+
"args": ["run", "--rm", "-i", "--network", "host", "-e", "SIGLENT_SDG_IP=192.168.1.126", "ghcr.io/magnusjohansson/siglent-sdg-mcp:latest"]
|
|
450
|
+
```
|
|
451
|
+
Note: `--network host` does not work on macOS or Windows Docker Desktop.
|
|
452
|
+
|
|
453
|
+
### Docker: wrong architecture / exec format error
|
|
454
|
+
|
|
455
|
+
The published image supports `linux/amd64` and `linux/arm64`. Docker should pull the correct one automatically. If you see an exec format error, pull explicitly:
|
|
456
|
+
|
|
457
|
+
```bash
|
|
458
|
+
docker pull --platform linux/amd64 ghcr.io/magnusjohansson/siglent-sdg-mcp:latest
|
|
459
|
+
```
|
|
460
|
+
|
|
461
|
+
### "CHDR" appears in responses
|
|
462
|
+
|
|
463
|
+
This shouldn't happen — the server sets `CHDR OFF` on connect. If you see command headers in responses, try disconnecting and reconnecting.
|
|
464
|
+
|
|
465
|
+
## License
|
|
466
|
+
|
|
467
|
+
MIT — see [LICENSE](LICENSE) for details.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export declare class SiglentConnection {
|
|
2
|
+
private socket;
|
|
3
|
+
private host;
|
|
4
|
+
private port;
|
|
5
|
+
private dataBuffer;
|
|
6
|
+
private responseResolve;
|
|
7
|
+
private responseReject;
|
|
8
|
+
private responseTimer;
|
|
9
|
+
private expectedBinaryLength;
|
|
10
|
+
private binaryDataStart;
|
|
11
|
+
private headerParsed;
|
|
12
|
+
private queryQueue;
|
|
13
|
+
private queryRunning;
|
|
14
|
+
connect(host: string, port?: number): Promise<string>;
|
|
15
|
+
disconnect(): void;
|
|
16
|
+
isConnected(): boolean;
|
|
17
|
+
getConnectionInfo(): string;
|
|
18
|
+
sendCommand(cmd: string): Promise<void>;
|
|
19
|
+
query(cmd: string, timeout?: number): Promise<string>;
|
|
20
|
+
queryBinary(cmd: string, timeout?: number): Promise<Buffer>;
|
|
21
|
+
private enqueueQuery;
|
|
22
|
+
private drainQueue;
|
|
23
|
+
private setupSocketListeners;
|
|
24
|
+
private tryResolve;
|
|
25
|
+
private clearPending;
|
|
26
|
+
private ensureConnected;
|
|
27
|
+
private delay;
|
|
28
|
+
}
|
|
29
|
+
export declare const connection: SiglentConnection;
|