bigskymx-mcp
Controls a Strymon BigSky MX reverb pedal over USB MIDI, enabling preset management, parameter tweaking, and machine configuration from Claude or the command line.
README
bigskymx-mcp
Control a Strymon BigSky MX over USB MIDI, from a command line or from Claude.
Getting started
You need:
- Nixie 2, Strymon's free editor
- Python 3.10 or newer
- git
Developed and tested on macOS. It should work anywhere python-rtmidi does; on Linux that means ALSA development headers if pip has to build it from source.
1. Connect the pedal to your computer
2. Open Nixie 2 and leave it running
A freshly connected pedal sends no MIDI until an editor session exists. Nixie does not interfere with this tool.
3. Install
git clone https://github.com/levinelson/bigskymx-mcp.git
cd bigskymx-mcp
python3 -m venv .venv
.venv/bin/pip install -e ".[mcp]"
Drop [mcp] if you only want the command line. This puts bigsky in .venv/bin, not on your PATH; uv tool install . or pipx install . gets you a plain bigsky anywhere. Examples below use the bare name.
4. Check it works
.venv/bin/bigsky ports # BigSkyMX should be listed and auto-detected
.venv/bin/bigsky state # prints the loaded preset and both engines
| Symptom | Cause or fix |
|---|---|
ports does not list BigSkyMX |
cable or connection |
ports finds it, state says it is not broadcasting |
Nixie 2 is not open |
| the stream stops after working | bigsky preset 0 restarts it |
| still stopped with Nixie open | quit Nixie |
Commands
Everyday
bigsky ports # list MIDI ports, show auto-detect
bigsky state # read the loaded preset
bigsky state --config # read global settings
bigsky param TYPE NONLINEAR --engine 1 # switch reverb machine
bigsky param SHAPE BOUNCE --engine 1 # machine-specific, by name
bigsky param Decay 100 --engine 1 # 0-127, scaled to the full range
bigsky param DUAL "SERIES 1 >> 2" # routing
bigsky param "INF MODE" INFINITE --engine 1
bigsky preset 42 # recall a slot, 0-299
bigsky load "presets/PAD.json" # restore a sound to the edit buffer
bigsky backup out/ # every slot to JSON plus a .syx
bigsky machines # every machine and its parameters
bigsky monitor # print incoming MIDI
Choice parameters take names, not numbers. --channel defaults to auto and reads the channel off the pedal.
Offline, no pedal needed
| Command | Does |
|---|---|
bigsky show FILE.syx |
decode a preset bank |
bigsky export FILE.syx DIR/ |
bank to editable JSON files |
bigsky build DIR/ FILE.syx |
JSON files back to a bank |
bigsky diff A.syx B.syx |
byte-diff two banks |
Working on the protocol
| Command | Does |
|---|---|
bigsky probe |
sweep the SysEx opcode space (needs --yes) |
bigsky dump |
send one SysEx request, save the reply (needs --yes) |
bigsky discover-cc |
rebuild the CC map by watching the pedal |
bigsky verify-types |
walk every reverb machine |
bigsky emulate |
impersonate the pedal to capture what Nixie sends |
bigsky proxy |
sit between Nixie and the pedal |
scripts/full_review.py sets every parameter of every machine on both engines and checks the pedal's report. It passes 299/303; the four failures are INF MIX, which has no CC.
Use with Claude
claude mcp add bigsky -- /full/path/to/.venv/bin/bigsky-mcp
Claude Desktop, in claude_desktop_config.json:
{
"mcpServers": {
"bigsky": {
"command": "/full/path/to/.venv/bin/bigsky-mcp"
}
}
}
The path must be absolute. The client launches the server and does not inherit your shell.
| Tool | Does | Read-only | Destructive |
|---|---|---|---|
bigsky_get_state |
read the loaded preset and both engines | yes | no |
bigsky_list_machines |
the 12 reverb machines | yes | no |
bigsky_describe_machine |
one machine's parameters, ranges and choices | yes | no |
bigsky_set_params |
set any number of parameters on either engine | no | no |
bigsky_recall_preset |
recall a slot, 0-299 | no | yes, discards unsaved edits |
bigsky_list_preset_files |
saved sound files | yes | no |
bigsky_load_preset_file |
restore one to the edit buffer | no | yes, discards unsaved edits |
bigsky_save_preset_file |
write the current sound to a file | no | yes, can replace a file |
bigsky_set_params takes a whole change at once and applies it in the order the pedal requires:
- Shared globals, because
DUALandPERSISTreload the preset - The machine type
- That machine's own parameters
OUTPUT LEVEL,PANandINF MODE, which survive a type change- The continuous knobs
bigsky_save_preset_file refuses to replace an existing file unless asked twice.
Set BIGSKY_PRESETS in the server's env to keep sounds somewhere other than presets/.
What it cannot do
- Store to a numbered slot. I haven't found a MIDI message that does this. Dial a sound in and then save it manually on the pedal or in Nixie.
- Set
INF MIX. It is in Strymon's schema and in no CC table. - Assign PARAM 1 and PARAM 2. CC 19-22 drive whatever is already assigned; nothing addresses the assignment. Presets store it as a name, so it looks settable.
loadlists these separately from real failures.
The CC map
Transcribed in cc.py from the manual (Rev B, pages 70-76). Scaled means CC 0-127 spans a wider internal range; direct means the CC value is the value and clamps at the maximum.
| Parameter | Engine 1 | Engine 2 | Range | Kind |
|---|---|---|---|---|
| Type | 1 | 2 | 0-11 | direct, machine index |
| Decay | 3 | 4 | 0-127 | scaled, ms internally |
| Pre-Delay | 5 | 6 | 0-127 | scaled, ms internally |
| Output Level | 7 | 8 | 0-16 | direct |
| Pan | 9 | 10 | 0-16 | direct |
| Tone | 11 | 12 | 0-127 | scaled to 0-255 |
| Mod | 13 | 14 | 0-127 | scaled to 0-255 |
| Mix | 15 | 16 | 0-127 | scaled to 0-255 |
| INF MODE | 17 | 18 | 0-2 | direct, freeze / infinite / off |
| Param1 | 19 | 20 | 0-127 | scaled, drives the assigned knob |
| Param2 | 21 | 22 | 0-127 | scaled, drives the assigned knob |
| Low End | 23 | 24 | 0-20 | direct |
| MIDI Clock (Magneto) | 31 | 32 | 0-1 | direct |
Machine-specific parameters are in cc.MACHINE_CC.
| Shared control | CC | Takes |
|---|---|---|
| Boost | 79 | 0-60 |
| Persist | 84 | ON, OFF |
| INF LATCH | 98 | MOMENTARY, LATCHING |
| DUAL | 99 | OFF, PARALLEL, SERIES 1 >> 2, SERIES 1 << 2, SPLIT 1L * 2R, SPLIT 1R * 2L |
| Hardware control | CC | Notes |
|---|---|---|
| Bank up / down | 80 / 81 | also the A and B footswitches |
| Infinite footswitch | 82 | acts as the physical switch |
| Value encoder | 83 | changes the loaded preset |
| Infinite on / off | 97 | |
| Expression | 100 | |
| Tap | 101 | |
| Bypass | 102 |
Gotcha: sweeping CCs blindly hits 83 and silently swaps the preset out from under whatever you are testing.
Two corrections to the manual, both confirmed on hardware:
- Persist is inverted. The manual says 0 = Off. The pedal reports CC 84 = 0 as ON.
- Shimmer Shift 2 is CC 73/74, not the printed 72/73, which collides with Shift 1.
The frame format
Presets and state are UTF-8 JSON inside SysEx.
F0 00 01 55 18 01 39 00 01 01 01 00 00 LL LL {"...json..."} F7
|________| | | | | | | |___|
Strymon | | | | | | total length, 7-bit big endian
mfr ID | | | | | payload type: 01=state 02=config 06=preset
| | | | verb: 01=data 02=request 4A=select a slot
| | | 7F on a preset, 00 on state/config
| | opcode 0x39 = data (0x43 = firmware update; avoid)
| device id 0x01
product 0x18 = BigSky MX
Byte order is product, then device, then opcode.
The JSON starts at byte 14, always. Do not search for the first {: bytes 12-13 carry the length, and a low byte of 0x7B is itself an ASCII {, so the search starts one byte early and the parse fails. This happens whenever the total length mod 128 is 123. Use sysex.payload_json.
The two directions use different header lengths. Pedal-to-host is 14 bytes before the JSON. Host-to-pedal is 10, with no length bytes: 00 01 55 18 01 39 00 01 01 01 then the JSON.
State frames can be partial, one parameter at a time:
{ "state": { "channel": [{ "TYPE": "CLOUD", "LOW END": 10 }, {}] } }
Opcodes
The pedal answers 0x46 to anything it does not implement.
| Opcode | Reply | What it is |
|---|---|---|
0x21 |
14 bytes | Read ESN. Nixie's device probe. |
0x32 |
00 01 00 00 |
Unidentified. Version or capability word. |
0x39 |
(silent) | Data. Silence means "send a payload". |
0x56 |
0x45 (ACK) |
Accepted and executed, no front-panel change. Unidentified. |
0x00 |
(silent) | Recognised, wants a payload. |
| anything else | 0x46 |
Not implemented. |
The gen-1 command set is gone. These all NAK:
| Opcode | Was |
|---|---|
0x62 |
write patch |
0x63 |
request patch |
0x64 |
enter save mode |
0x22 |
get current state |
Only 0x21 carried over. All four are documented for TimeLine, Mobius and gen-1 BigSky in Strymon's own librarian, strymon/spl, in spl/DcMidiDevDefs.h.
0x4A selects a slot. It is not a save, and Nixie sends the identical message when you click a preset in its list.
Gotchas
- The pedal ignores every message on a MIDI channel other than its own, with no error. A wrong channel looks exactly like a working connection.
- Writes go over CC. Sending the pedal its own state frame back also works and reaches full internal resolution, but stops applying after a while and silently reverts.
live.set_paramstill exposes it. - A JSON state write ignores a value of
0, leaving the old value. - Machine type cannot be changed by a JSON write. It needs CC 1/2.
DUALandPERSISTmake the pedal reload the preset, reverting edits made before them. Set globals first.- The pedal echoes what you sent before applying its own limits, so verifying too quickly reports success for a value that then gets clamped.
- Reading the stream without draining returns a stale snapshot.
- Re-sending a program change for the current preset does not reload it.
- Decay and Pre-Delay are milliseconds on a non-linear per-machine curve, so the CC value is searched for rather than computed. Mix, Tone and Mod land within one CC step of the request.
Safety
Firmware updates use opcode 0x43. Everything here stays on 0x39, so none of it can trigger a flash. probe and dump can send undocumented opcodes and are gated behind --yes.
Run bigsky backup out/ before experimenting.
Your own sounds
presets/ ships empty and is gitignored. Anything you put there is picked up by bigsky load and by the MCP preset tools.
Not affiliated with Strymon
This is independent interoperability work, not authorized or endorsed by Strymon. Strymon, BigSky and Nixie are trademarks of their owner. Everything here came from observing a pedal I own and from the published manual, except bigsky/schema.json, which was derived from the Nixie 2 binary.
Written by Claude Code.
License
MIT. See LICENSE.
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.
Neon Database
MCP server for interacting with Neon Management API and databases
E2B
Using MCP to run code via e2b.
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.