labmcp-brainflow 0.1.0__tar.gz

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.
@@ -0,0 +1,15 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ .venv/
4
+ .pytest_cache/
5
+ .ruff_cache/
6
+ dist/
7
+ build/
8
+ *.egg-info/
9
+ .DS_Store
10
+ *.jsonl
11
+ !**/fixtures/*.jsonl
12
+ .idea/
13
+ .vscode/
14
+
15
+ CLAUDE.md
@@ -0,0 +1,143 @@
1
+ Metadata-Version: 2.5
2
+ Name: labmcp-brainflow
3
+ Version: 0.1.0
4
+ Summary: MCP server for EEG/EMG/ECG/PPG biosensing boards via BrainFlow (OpenBCI, Muse, Neurosity, g.tec Unicorn, BrainBit, ...): stream, record, band powers, markers, signal quality.
5
+ Project-URL: Homepage, https://github.com/K-Dense-AI/lab-instrument-mcps/tree/main/servers/health/brainflow-biosensors
6
+ Author: K-Dense and LabMCP contributors
7
+ License-Expression: Apache-2.0
8
+ Keywords: bci,brainflow,ecg,eeg,emg,lab-instrument,mcp,muse,neuroscience,openbci,ppg
9
+ Requires-Python: >=3.10
10
+ Requires-Dist: brainflow>=5.21
11
+ Requires-Dist: labmcp<0.2,>=0.1
12
+ Requires-Dist: numpy>=1.24
13
+ Description-Content-Type: text/markdown
14
+
15
+ # BrainFlow Biosensing Boards — MCP Server
16
+
17
+ <!-- mcp-name: io.github.K-Dense-AI/labmcp-brainflow -->
18
+
19
+ Let an AI agent stream, record and analyse **EEG, EMG, ECG, EOG, PPG and EDA** from the biosensing boards supported by the open-source **[BrainFlow](https://brainflow.org)** SDK: OpenBCI, Muse, Neurosity, g.tec Unicorn, BrainBit and many more. It covers recording with event markers, EEG band powers and per-electrode signal-quality checks.
20
+
21
+ > **Research use only. This is not a medical device.** Do not use it to diagnose, monitor or treat anyone. Follow the board manufacturer's safety instructions (battery operation, electrical isolation, skin preparation). This server does not change any of them.
22
+
23
+ | | |
24
+ |---|---|
25
+ | **Package** | `labmcp-brainflow` |
26
+ | **Instruments** | OpenBCI Cyton, Cyton+Daisy, Ganglion, Galea (USB dongle, BLE, WiFi Shield) · Muse 2 / S / S Athena / 2016 · Neurosity Crown / Notion · g.tec Unicorn · BrainBit · Callibri · Enophone · Mentalab Explore · EmotiBit · FreeEEG32/128 · NeuroPawn Knight · Shimmer3 · any other board in BrainFlow's `BoardIds` |
27
+ | **Interfaces** | USB serial dongle, Bluetooth LE (native or BLED112 dongle), WiFi, vendor SDKs (all through BrainFlow) |
28
+ | **Protocol** | BrainFlow SDK ≥ 5.21: `BoardShim`, `BrainFlowInputParams`, `DataFilter` ([User API](https://brainflow.readthedocs.io/en/stable/UserAPI.html), [Supported Boards](https://brainflow.readthedocs.io/en/stable/SupportedBoards.html), [Data Format](https://brainflow.readthedocs.io/en/stable/DataFormatDesc.html)) |
29
+ | **Status** | 🧪 **simulated**: tested against BrainFlow's own synthetic board and a built-in fake, not yet verified on hardware. [Report a hardware test](https://github.com/K-Dense-AI/lab-instrument-mcps/issues/new?template=hardware-verification.yml) |
30
+
31
+ ## Try it without hardware
32
+
33
+ ```bash
34
+ uvx labmcp-brainflow --simulate --check
35
+ ```
36
+
37
+ `--simulate` runs **BrainFlow's own `SYNTHETIC_BOARD`**, so the real BrainFlow code path runs: 16 EXG channels at 250 Hz with sine waves at 5, 10, 15 … 80 Hz plus accelerometer, gyro, PPG, EDA and temperature rows. On platforms where BrainFlow's native library can't load, or with `--option simulator=fake`, a pure-numpy stand-in is used instead. It simulates an 8-channel, 250 Hz EEG headset with 1/f background, posterior alpha at 10 Hz and one badly attached electrode (Fp2, heavy 50 Hz pickup), so the signal-quality check has something to find.
38
+
39
+ ## Connect your board
40
+
41
+ 1. **Pick the board** with `--option board=<alias>` (or any BrainFlow `BoardIds` name such as `ANT_NEURO_EE_411_BOARD`, or a numeric id). The `list_supported_boards` tool prints this table too.
42
+ 2. **Give the connection detail** with `--address`. Depending on the board, BrainFlow expects a different `BrainFlowInputParams` field, and the server fills in the right one:
43
+
44
+ | Board (`--option board=`) | `--address` is | Required? | Notes |
45
+ |---|---|---|---|
46
+ | `cyton`, `cyton_daisy` | serial port of the USB dongle | yes | macOS: use `/dev/cu.usbserial-*`, not `/dev/tty.*` |
47
+ | `ganglion` (native BLE) | Bluetooth MAC | no (auto-discovery) | FW 2 boards: `--option other_info=fw:2` |
48
+ | `ganglion_dongle` | serial port of the BLED112 dongle | yes | optional `--option mac_address=` |
49
+ | `cyton_wifi`, `cyton_daisy_wifi`, `ganglion_wifi` | WiFi Shield IP (192.168.4.1 in direct mode) | no (SSDP) | `--option ip_port=` (default 6789) |
50
+ | `muse_2`, `muse_s`, `muse_s_athena`, `muse_2016` | Bluetooth MAC | no | `--option serial_number=Muse-XXXX`; PPG: `--option other_info=p50` (Muse 2) / `p61` (Muse S) |
51
+ | `muse_2_bled`, `muse_s_bled` | serial port of the BLED112 dongle | yes | |
52
+ | `crown`, `notion_1`, `notion_2` | device serial number | no | same network, broadcast must be allowed |
53
+ | `unicorn`, `brainbit` | device serial number | no | Unicorn: pair with the supplied dongle |
54
+ | `enophone`, `explore_4`, `explore_8` | Bluetooth MAC | Linux only | |
55
+ | `emotibit` | network broadcast address | no | |
56
+ | `freeeeg32`, `freeeeg128`, `neuropawn_knight`, `shimmer3`, `ironbci_32` | serial port | yes | |
57
+ | `playback` | path of a file saved in BrainFlow format | yes | `--option master_board=<board it was recorded with>` |
58
+ | `synthetic` | nothing | | BrainFlow's synthetic board |
59
+
60
+ For a board that isn't listed, the server infers the field from the address format: `COM3` or `/dev/…` becomes a serial port, `AA:BB:…` a MAC address, `a.b.c.d` an IP address, and anything else a serial number. You can also set any field directly with `--option serial_port=… / mac_address=… / ip_address=… / serial_number=… / other_info=… / timeout=…`.
61
+
62
+ 3. **Test the connection:**
63
+ ```bash
64
+ uvx labmcp-brainflow --option board=cyton --address /dev/cu.usbserial-DM00Q0QN --check # macOS
65
+ uvx labmcp-brainflow --option board=cyton_daisy --address COM3 --check # Windows
66
+ uvx labmcp-brainflow --option board=muse_2 --option serial_number=Muse-1A2B --check
67
+ uvx labmcp-brainflow --option board=unicorn --check
68
+ ```
69
+ Close other programs that hold the device (OpenBCI GUI, Muse app) first. On Linux, add yourself to the `dialout` group for serial ports.
70
+
71
+ ## Add to your MCP client
72
+
73
+ **Claude Code**
74
+ ```bash
75
+ claude mcp add eeg -- uvx labmcp-brainflow --option board=cyton --address /dev/ttyUSB0
76
+ ```
77
+
78
+ **Claude Desktop / Cursor / Windsurf** (`claude_desktop_config.json`, `.cursor/mcp.json`, …)
79
+ ```json
80
+ {
81
+ "mcpServers": {
82
+ "eeg": {
83
+ "command": "uvx",
84
+ "args": ["labmcp-brainflow", "--option", "board=cyton", "--address", "/dev/ttyUSB0"]
85
+ }
86
+ }
87
+ }
88
+ ```
89
+
90
+ With `--read-only`, the agent can still record and analyse data (a temporary stream is started for each recording) but cannot leave the stream running, insert markers or send `configure_board` commands.
91
+
92
+ ## Tools
93
+
94
+ <!-- TOOLS:START -->
95
+ | Tool | Kind | Description |
96
+ |---|---|---|
97
+ | `configure_board` | 🎛 control | Send a board-specific configuration command through BrainFlow's config_board (e.g. OpenBCI channel settings 'x1060110X', test signals, or Muse presets 'p50'/'p61' to enable PPG). Only acquisition settings of the amplifier change. Consult the board's SDK documentation first. |
98
+ | `get_band_powers` | 👁 read | EEG band powers (delta 1-4, theta 4-8, alpha 8-13, beta 13-30, gamma 30-50 Hz) over the most recent `window_s` seconds: BrainFlow's channel-averaged relative powers plus per-channel absolute (uV^2) and relative powers and the peak frequency. Records a fresh window if not streaming. |
99
+ | `get_board_info` | 👁 read | Describe the connected board: channel names by type (EEG/EMG/ECG/EOG share the EXG rows on most boards), sampling rate, available presets (data buffers) and streaming state. |
100
+ | `get_command_log` | 👁 read | Return the most recent raw commands sent to / replies received from the instrument (newest last). Useful for debugging and for recording what was done. |
101
+ | `get_connection_info` | 👁 read | Report which instrument is connected (identity, address, simulated or real), whether the server is read-only, and the active safety limits. Call this first. |
102
+ | `get_signal_quality` | 👁 read | Check every EXG channel for common electrode problems: flat line (disconnected), railed (amplifier saturated, OpenBCI Cyton boards), strong 50/60 Hz mains noise (poor contact or missing reference), and implausibly high amplitude (movement, muscle, loose electrode). |
103
+ | `insert_marker` | 🎛 control | Write an event marker into the data stream at the current sample (for event-related experiments: stimulus onsets, condition changes). Requires `start_streaming`; markers appear in `record` results and saved files. |
104
+ | `list_supported_boards` | 👁 read | List common BrainFlow boards: the `--option board=` alias, BrainFlow board id, and which connection detail `--address` must hold (serial port, Bluetooth MAC, IP address or serial number). Any other BrainFlow BoardIds name or numeric id is accepted too. Does not need a board. |
105
+ | `reconnect` | 🛑 safety | Close and re-open the connection to the instrument (e.g. after it was power cycled or a cable was re-plugged). |
106
+ | `record` | 👁 read | Record `duration_s` seconds and return per-channel statistics, event markers and downsampled traces. Uses the live stream if one is running, otherwise starts a temporary one. The full data (every row, full sampling rate) can be written to `save_path`. |
107
+ | `start_streaming` | 🎛 control | Start continuous acquisition into BrainFlow's ring buffer (the board's radio/LEDs switch on; nothing is applied to the participant). Needed for `insert_marker`; `record` then reads from the live stream. Call `stop_streaming` when finished. |
108
+ | `stop_streaming` | 🎛 control | Stop acquisition (saves battery). Data already in the buffer is kept until the session is released (`reconnect`) or read. |
109
+ <!-- TOOLS:END -->
110
+
111
+ ## Safety limits
112
+
113
+ | Limit | Default | Meaning |
114
+ |---|---|---|
115
+ | `max_record_duration_s` | 60 s | Longest recording or analysis window (`record`, `get_band_powers`, `get_signal_quality`) an agent may request |
116
+
117
+ Override at launch: `--limit max_record_duration_s=600`. No tool here applies anything to the participant. BrainFlow boards only measure.
118
+
119
+ ## Example prompts
120
+
121
+ - "Check the signal quality on all 8 Cyton channels and tell me which electrodes need more gel."
122
+ - "Record 30 s eyes-closed and 30 s eyes-open, save both as CSV in ~/data/sub-01/, and compare occipital alpha power."
123
+ - "Start streaming. I'll run an oddball task: insert marker 1 for standards and 2 for targets when I tell you. Then save the session in BrainFlow format."
124
+ - "What's the peak alpha frequency on O1 and O2 over the last 10 seconds?"
125
+ - "Is there 50 or 60 Hz mains noise in this setup, and on which channels?"
126
+ - "List the boards you support and tell me how to connect my Muse S."
127
+
128
+ ## Notes
129
+
130
+ - **How the band powers are computed.** `average_relative` comes from BrainFlow's `DataFilter.get_avg_band_powers(apply_filter=True)`: detrend, 48–52 and 58–62 Hz band-stop, 2–45 Hz band-pass, Welch PSD, then bands of 1–4, 4–8, 8–13, 13–30 and 30–50 Hz averaged over channels and normalised to sum to 1. Per-channel values use detrend, a 50/60 Hz notch and a 1–45 Hz 4th-order zero-phase Butterworth (BrainFlow `DataFilter`), followed by a Welch PSD (Hann window, 50 % overlap, ≈0.5 Hz bins). Absolute band power is the integrated PSD in µV², and gamma is effectively 30–45 Hz.
131
+ - **Signal-quality verdicts** (EEG-oriented thresholds): `flat` means the raw SD is below 0.5 µV (disconnected); `railed` means at least 90 % of the ADS1299 input range is used (OpenBCI Cyton family only, using BrainFlow's formula with gain 24, set by `--option exg_gain=`); `line_noise` means 50 or 60 Hz power exceeds the whole 1–45 Hz power; `high_amplitude` means the band-passed RMS is above 100 µV. EMG/ECG recordings will naturally be "high amplitude".
132
+ - **Units.** BrainFlow returns EXG in µV "wherever possible". The OYMotion gForce armbands return ADC counts. Accelerometer, PPG and similar channels use board-specific units. Timestamps are Unix seconds.
133
+ - **Presets.** Some boards stream several buffers with different sampling rates, for example Muse EEG (default), IMU (auxiliary) and PPG (ancillary). Pass `preset=` to `get_board_info` and `record`.
134
+ - **Markers** go into the default preset's marker row and need an active stream (`start_streaming`). You can insert them while `record` is running. Value 0 is reserved.
135
+ - **Saved files.** `save_format="csv"` writes labelled columns for every row. `save_format="brainflow"` writes `DataFilter.write_file` output, which you can replay with `--option board=playback --address file.csv --option master_board=<board>`.
136
+ - `configure_board` passes a string straight to the board firmware through BrainFlow's `config_board`, for example OpenBCI channel settings or Muse presets. It only changes acquisition settings, but check the board's SDK documentation for valid commands.
137
+ - `reconnect` (and stopping the server) stops the stream and calls `release_session`, which frees the serial port or BLE connection.
138
+
139
+ ## Hardware verification
140
+
141
+ | Model | Firmware | Interface | Verified by | Date |
142
+ |---|---|---|---|---|
143
+ | *none yet: [be the first](https://github.com/K-Dense-AI/lab-instrument-mcps/issues/new?template=hardware-verification.yml)* | | | | |
@@ -0,0 +1,129 @@
1
+ # BrainFlow Biosensing Boards — MCP Server
2
+
3
+ <!-- mcp-name: io.github.K-Dense-AI/labmcp-brainflow -->
4
+
5
+ Let an AI agent stream, record and analyse **EEG, EMG, ECG, EOG, PPG and EDA** from the biosensing boards supported by the open-source **[BrainFlow](https://brainflow.org)** SDK: OpenBCI, Muse, Neurosity, g.tec Unicorn, BrainBit and many more. It covers recording with event markers, EEG band powers and per-electrode signal-quality checks.
6
+
7
+ > **Research use only. This is not a medical device.** Do not use it to diagnose, monitor or treat anyone. Follow the board manufacturer's safety instructions (battery operation, electrical isolation, skin preparation). This server does not change any of them.
8
+
9
+ | | |
10
+ |---|---|
11
+ | **Package** | `labmcp-brainflow` |
12
+ | **Instruments** | OpenBCI Cyton, Cyton+Daisy, Ganglion, Galea (USB dongle, BLE, WiFi Shield) · Muse 2 / S / S Athena / 2016 · Neurosity Crown / Notion · g.tec Unicorn · BrainBit · Callibri · Enophone · Mentalab Explore · EmotiBit · FreeEEG32/128 · NeuroPawn Knight · Shimmer3 · any other board in BrainFlow's `BoardIds` |
13
+ | **Interfaces** | USB serial dongle, Bluetooth LE (native or BLED112 dongle), WiFi, vendor SDKs (all through BrainFlow) |
14
+ | **Protocol** | BrainFlow SDK ≥ 5.21: `BoardShim`, `BrainFlowInputParams`, `DataFilter` ([User API](https://brainflow.readthedocs.io/en/stable/UserAPI.html), [Supported Boards](https://brainflow.readthedocs.io/en/stable/SupportedBoards.html), [Data Format](https://brainflow.readthedocs.io/en/stable/DataFormatDesc.html)) |
15
+ | **Status** | 🧪 **simulated**: tested against BrainFlow's own synthetic board and a built-in fake, not yet verified on hardware. [Report a hardware test](https://github.com/K-Dense-AI/lab-instrument-mcps/issues/new?template=hardware-verification.yml) |
16
+
17
+ ## Try it without hardware
18
+
19
+ ```bash
20
+ uvx labmcp-brainflow --simulate --check
21
+ ```
22
+
23
+ `--simulate` runs **BrainFlow's own `SYNTHETIC_BOARD`**, so the real BrainFlow code path runs: 16 EXG channels at 250 Hz with sine waves at 5, 10, 15 … 80 Hz plus accelerometer, gyro, PPG, EDA and temperature rows. On platforms where BrainFlow's native library can't load, or with `--option simulator=fake`, a pure-numpy stand-in is used instead. It simulates an 8-channel, 250 Hz EEG headset with 1/f background, posterior alpha at 10 Hz and one badly attached electrode (Fp2, heavy 50 Hz pickup), so the signal-quality check has something to find.
24
+
25
+ ## Connect your board
26
+
27
+ 1. **Pick the board** with `--option board=<alias>` (or any BrainFlow `BoardIds` name such as `ANT_NEURO_EE_411_BOARD`, or a numeric id). The `list_supported_boards` tool prints this table too.
28
+ 2. **Give the connection detail** with `--address`. Depending on the board, BrainFlow expects a different `BrainFlowInputParams` field, and the server fills in the right one:
29
+
30
+ | Board (`--option board=`) | `--address` is | Required? | Notes |
31
+ |---|---|---|---|
32
+ | `cyton`, `cyton_daisy` | serial port of the USB dongle | yes | macOS: use `/dev/cu.usbserial-*`, not `/dev/tty.*` |
33
+ | `ganglion` (native BLE) | Bluetooth MAC | no (auto-discovery) | FW 2 boards: `--option other_info=fw:2` |
34
+ | `ganglion_dongle` | serial port of the BLED112 dongle | yes | optional `--option mac_address=` |
35
+ | `cyton_wifi`, `cyton_daisy_wifi`, `ganglion_wifi` | WiFi Shield IP (192.168.4.1 in direct mode) | no (SSDP) | `--option ip_port=` (default 6789) |
36
+ | `muse_2`, `muse_s`, `muse_s_athena`, `muse_2016` | Bluetooth MAC | no | `--option serial_number=Muse-XXXX`; PPG: `--option other_info=p50` (Muse 2) / `p61` (Muse S) |
37
+ | `muse_2_bled`, `muse_s_bled` | serial port of the BLED112 dongle | yes | |
38
+ | `crown`, `notion_1`, `notion_2` | device serial number | no | same network, broadcast must be allowed |
39
+ | `unicorn`, `brainbit` | device serial number | no | Unicorn: pair with the supplied dongle |
40
+ | `enophone`, `explore_4`, `explore_8` | Bluetooth MAC | Linux only | |
41
+ | `emotibit` | network broadcast address | no | |
42
+ | `freeeeg32`, `freeeeg128`, `neuropawn_knight`, `shimmer3`, `ironbci_32` | serial port | yes | |
43
+ | `playback` | path of a file saved in BrainFlow format | yes | `--option master_board=<board it was recorded with>` |
44
+ | `synthetic` | nothing | | BrainFlow's synthetic board |
45
+
46
+ For a board that isn't listed, the server infers the field from the address format: `COM3` or `/dev/…` becomes a serial port, `AA:BB:…` a MAC address, `a.b.c.d` an IP address, and anything else a serial number. You can also set any field directly with `--option serial_port=… / mac_address=… / ip_address=… / serial_number=… / other_info=… / timeout=…`.
47
+
48
+ 3. **Test the connection:**
49
+ ```bash
50
+ uvx labmcp-brainflow --option board=cyton --address /dev/cu.usbserial-DM00Q0QN --check # macOS
51
+ uvx labmcp-brainflow --option board=cyton_daisy --address COM3 --check # Windows
52
+ uvx labmcp-brainflow --option board=muse_2 --option serial_number=Muse-1A2B --check
53
+ uvx labmcp-brainflow --option board=unicorn --check
54
+ ```
55
+ Close other programs that hold the device (OpenBCI GUI, Muse app) first. On Linux, add yourself to the `dialout` group for serial ports.
56
+
57
+ ## Add to your MCP client
58
+
59
+ **Claude Code**
60
+ ```bash
61
+ claude mcp add eeg -- uvx labmcp-brainflow --option board=cyton --address /dev/ttyUSB0
62
+ ```
63
+
64
+ **Claude Desktop / Cursor / Windsurf** (`claude_desktop_config.json`, `.cursor/mcp.json`, …)
65
+ ```json
66
+ {
67
+ "mcpServers": {
68
+ "eeg": {
69
+ "command": "uvx",
70
+ "args": ["labmcp-brainflow", "--option", "board=cyton", "--address", "/dev/ttyUSB0"]
71
+ }
72
+ }
73
+ }
74
+ ```
75
+
76
+ With `--read-only`, the agent can still record and analyse data (a temporary stream is started for each recording) but cannot leave the stream running, insert markers or send `configure_board` commands.
77
+
78
+ ## Tools
79
+
80
+ <!-- TOOLS:START -->
81
+ | Tool | Kind | Description |
82
+ |---|---|---|
83
+ | `configure_board` | 🎛 control | Send a board-specific configuration command through BrainFlow's config_board (e.g. OpenBCI channel settings 'x1060110X', test signals, or Muse presets 'p50'/'p61' to enable PPG). Only acquisition settings of the amplifier change. Consult the board's SDK documentation first. |
84
+ | `get_band_powers` | 👁 read | EEG band powers (delta 1-4, theta 4-8, alpha 8-13, beta 13-30, gamma 30-50 Hz) over the most recent `window_s` seconds: BrainFlow's channel-averaged relative powers plus per-channel absolute (uV^2) and relative powers and the peak frequency. Records a fresh window if not streaming. |
85
+ | `get_board_info` | 👁 read | Describe the connected board: channel names by type (EEG/EMG/ECG/EOG share the EXG rows on most boards), sampling rate, available presets (data buffers) and streaming state. |
86
+ | `get_command_log` | 👁 read | Return the most recent raw commands sent to / replies received from the instrument (newest last). Useful for debugging and for recording what was done. |
87
+ | `get_connection_info` | 👁 read | Report which instrument is connected (identity, address, simulated or real), whether the server is read-only, and the active safety limits. Call this first. |
88
+ | `get_signal_quality` | 👁 read | Check every EXG channel for common electrode problems: flat line (disconnected), railed (amplifier saturated, OpenBCI Cyton boards), strong 50/60 Hz mains noise (poor contact or missing reference), and implausibly high amplitude (movement, muscle, loose electrode). |
89
+ | `insert_marker` | 🎛 control | Write an event marker into the data stream at the current sample (for event-related experiments: stimulus onsets, condition changes). Requires `start_streaming`; markers appear in `record` results and saved files. |
90
+ | `list_supported_boards` | 👁 read | List common BrainFlow boards: the `--option board=` alias, BrainFlow board id, and which connection detail `--address` must hold (serial port, Bluetooth MAC, IP address or serial number). Any other BrainFlow BoardIds name or numeric id is accepted too. Does not need a board. |
91
+ | `reconnect` | 🛑 safety | Close and re-open the connection to the instrument (e.g. after it was power cycled or a cable was re-plugged). |
92
+ | `record` | 👁 read | Record `duration_s` seconds and return per-channel statistics, event markers and downsampled traces. Uses the live stream if one is running, otherwise starts a temporary one. The full data (every row, full sampling rate) can be written to `save_path`. |
93
+ | `start_streaming` | 🎛 control | Start continuous acquisition into BrainFlow's ring buffer (the board's radio/LEDs switch on; nothing is applied to the participant). Needed for `insert_marker`; `record` then reads from the live stream. Call `stop_streaming` when finished. |
94
+ | `stop_streaming` | 🎛 control | Stop acquisition (saves battery). Data already in the buffer is kept until the session is released (`reconnect`) or read. |
95
+ <!-- TOOLS:END -->
96
+
97
+ ## Safety limits
98
+
99
+ | Limit | Default | Meaning |
100
+ |---|---|---|
101
+ | `max_record_duration_s` | 60 s | Longest recording or analysis window (`record`, `get_band_powers`, `get_signal_quality`) an agent may request |
102
+
103
+ Override at launch: `--limit max_record_duration_s=600`. No tool here applies anything to the participant. BrainFlow boards only measure.
104
+
105
+ ## Example prompts
106
+
107
+ - "Check the signal quality on all 8 Cyton channels and tell me which electrodes need more gel."
108
+ - "Record 30 s eyes-closed and 30 s eyes-open, save both as CSV in ~/data/sub-01/, and compare occipital alpha power."
109
+ - "Start streaming. I'll run an oddball task: insert marker 1 for standards and 2 for targets when I tell you. Then save the session in BrainFlow format."
110
+ - "What's the peak alpha frequency on O1 and O2 over the last 10 seconds?"
111
+ - "Is there 50 or 60 Hz mains noise in this setup, and on which channels?"
112
+ - "List the boards you support and tell me how to connect my Muse S."
113
+
114
+ ## Notes
115
+
116
+ - **How the band powers are computed.** `average_relative` comes from BrainFlow's `DataFilter.get_avg_band_powers(apply_filter=True)`: detrend, 48–52 and 58–62 Hz band-stop, 2–45 Hz band-pass, Welch PSD, then bands of 1–4, 4–8, 8–13, 13–30 and 30–50 Hz averaged over channels and normalised to sum to 1. Per-channel values use detrend, a 50/60 Hz notch and a 1–45 Hz 4th-order zero-phase Butterworth (BrainFlow `DataFilter`), followed by a Welch PSD (Hann window, 50 % overlap, ≈0.5 Hz bins). Absolute band power is the integrated PSD in µV², and gamma is effectively 30–45 Hz.
117
+ - **Signal-quality verdicts** (EEG-oriented thresholds): `flat` means the raw SD is below 0.5 µV (disconnected); `railed` means at least 90 % of the ADS1299 input range is used (OpenBCI Cyton family only, using BrainFlow's formula with gain 24, set by `--option exg_gain=`); `line_noise` means 50 or 60 Hz power exceeds the whole 1–45 Hz power; `high_amplitude` means the band-passed RMS is above 100 µV. EMG/ECG recordings will naturally be "high amplitude".
118
+ - **Units.** BrainFlow returns EXG in µV "wherever possible". The OYMotion gForce armbands return ADC counts. Accelerometer, PPG and similar channels use board-specific units. Timestamps are Unix seconds.
119
+ - **Presets.** Some boards stream several buffers with different sampling rates, for example Muse EEG (default), IMU (auxiliary) and PPG (ancillary). Pass `preset=` to `get_board_info` and `record`.
120
+ - **Markers** go into the default preset's marker row and need an active stream (`start_streaming`). You can insert them while `record` is running. Value 0 is reserved.
121
+ - **Saved files.** `save_format="csv"` writes labelled columns for every row. `save_format="brainflow"` writes `DataFilter.write_file` output, which you can replay with `--option board=playback --address file.csv --option master_board=<board>`.
122
+ - `configure_board` passes a string straight to the board firmware through BrainFlow's `config_board`, for example OpenBCI channel settings or Muse presets. It only changes acquisition settings, but check the board's SDK documentation for valid commands.
123
+ - `reconnect` (and stopping the server) stops the stream and calls `release_session`, which frees the serial port or BLE connection.
124
+
125
+ ## Hardware verification
126
+
127
+ | Model | Firmware | Interface | Verified by | Date |
128
+ |---|---|---|---|---|
129
+ | *none yet: [be the first](https://github.com/K-Dense-AI/lab-instrument-mcps/issues/new?template=hardware-verification.yml)* | | | | |
@@ -0,0 +1,45 @@
1
+ [project]
2
+ name = "labmcp-brainflow"
3
+ version = "0.1.0"
4
+ description = "MCP server for EEG/EMG/ECG/PPG biosensing boards via BrainFlow (OpenBCI, Muse, Neurosity, g.tec Unicorn, BrainBit, ...): stream, record, band powers, markers, signal quality."
5
+ readme = "README.md"
6
+ license = "Apache-2.0"
7
+ requires-python = ">=3.10"
8
+ authors = [{ name = "K-Dense and LabMCP contributors" }]
9
+ keywords = ["mcp", "lab-instrument", "eeg", "emg", "ecg", "ppg", "bci", "brainflow", "openbci", "muse", "neuroscience"]
10
+ dependencies = [
11
+ "labmcp>=0.1,<0.2",
12
+ "brainflow>=5.21",
13
+ "numpy>=1.24",
14
+ ]
15
+
16
+ [project.scripts]
17
+ labmcp-brainflow = "labmcp_brainflow.server:main"
18
+
19
+ [project.urls]
20
+ Homepage = "https://github.com/K-Dense-AI/lab-instrument-mcps/tree/main/servers/health/brainflow-biosensors"
21
+
22
+ [tool.labmcp]
23
+ name = "BrainFlow Biosensing Boards"
24
+ domain = "health"
25
+ category = "Biosignal acquisition (EEG/EMG/ECG/PPG)"
26
+ vendor = "OpenBCI, Interaxon (Muse), Neurosity, g.tec, BrainBit, Mentalab, EmotiBit and others (via BrainFlow)"
27
+ models = [
28
+ "OpenBCI Cyton / Cyton+Daisy / Ganglion / Galea (USB, BLE, WiFi Shield)",
29
+ "Muse 2 / Muse S / Muse S Athena / Muse 2016",
30
+ "Neurosity Crown / Notion 1 / Notion 2",
31
+ "g.tec Unicorn Hybrid Black",
32
+ "BrainBit, Callibri, Enophone, Mentalab Explore, EmotiBit, FreeEEG32/128, NeuroPawn Knight, Shimmer3",
33
+ "Any other board in BrainFlow's BoardIds",
34
+ ]
35
+ interfaces = ["USB (serial dongle)", "Bluetooth LE", "WiFi", "Vendor SDK (via BrainFlow)"]
36
+ protocol = "BrainFlow SDK (BoardShim / DataFilter)"
37
+ summary = "List boards, stream, record N seconds (stats + downsampled traces + CSV), EEG band powers, event markers, per-channel signal quality (flat, railed, mains noise). Research use only."
38
+ status = "simulated"
39
+
40
+ [build-system]
41
+ requires = ["hatchling"]
42
+ build-backend = "hatchling.build"
43
+
44
+ [tool.hatch.build.targets.wheel]
45
+ packages = ["src/labmcp_brainflow"]
@@ -0,0 +1,46 @@
1
+ {
2
+ "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
3
+ "name": "io.github.K-Dense-AI/labmcp-brainflow",
4
+ "title": "BrainFlow Biosensing Boards",
5
+ "description": "MCP server for EEG/EMG/ECG/PPG biosensing boards via BrainFlow (OpenBCI, Muse, Neurosity, g.tec Unic",
6
+ "version": "0.1.0",
7
+ "repository": {
8
+ "url": "https://github.com/K-Dense-AI/lab-instrument-mcps",
9
+ "source": "github",
10
+ "subfolder": "servers/health/brainflow-biosensors"
11
+ },
12
+ "websiteUrl": "https://github.com/K-Dense-AI/lab-instrument-mcps/tree/main/servers/health/brainflow-biosensors",
13
+ "packages": [
14
+ {
15
+ "registryType": "pypi",
16
+ "registryBaseUrl": "https://pypi.org",
17
+ "identifier": "labmcp-brainflow",
18
+ "version": "0.1.0",
19
+ "transport": {
20
+ "type": "stdio"
21
+ },
22
+ "environmentVariables": [
23
+ {
24
+ "name": "LABMCP_ADDRESS",
25
+ "description": "Instrument address, e.g. serial:///dev/ttyUSB0 or tcp://192.168.1.50:5025",
26
+ "isRequired": false
27
+ },
28
+ {
29
+ "name": "LABMCP_SIMULATE",
30
+ "description": "Set to 1 to use the built-in simulator (no hardware)",
31
+ "isRequired": false
32
+ },
33
+ {
34
+ "name": "LABMCP_READ_ONLY",
35
+ "description": "Set to 1 to disable all state-changing tools",
36
+ "isRequired": false
37
+ },
38
+ {
39
+ "name": "LABMCP_LIMITS",
40
+ "description": "Safety limit overrides, e.g. max_temperature_c=80",
41
+ "isRequired": false
42
+ }
43
+ ]
44
+ }
45
+ ]
46
+ }
@@ -0,0 +1 @@
1
+ """LabMCP server for EEG/EMG/ECG/PPG biosensing boards supported by BrainFlow."""