What it is
bci-mcp is an open-source (MIT) Python server that takes EEG from a headset and hands it to Claude, or any other Model Context Protocol (MCP) client, as plain numbers: band powers, signal quality, and six band-power ratios named focus, calm, attention, engagement, fatigue and meditation. It runs locally. A synthetic "demo brain" runs through the same code path as real hardware, so you can test the whole stack without a headset.

Clip from the README demo video: Claude Code calling bci-mcp for a focus reading (an earlier version of the tool).
Why
Assistants can read your screen and your code, but nothing about you. EEG is a physiological signal that consumer headsets can now measure reasonably well, so I wanted a small bridge between the two. Two examples: a neurofeedback session where Claude reads the score as you go, or an assistant that adjusts when an engagement estimate drops (a rough proxy, not a validated attention measure).
I also didn't want a black box. Give an LLM raw samples and it improvises signal processing. Give it one unexplained number and it treats that number as a fact about your mind.
Neurosity announced a hosted MCP server for its own headset in September 2025, and several single-device open-source servers appeared in 2026. I wanted one that runs locally, works with many devices and can be tested with no hardware.
How it works
Hardware. One URI scheme covers every source: synthetic://, OpenBCI Cyton/Ganglion and Muse 2/S through BrainFlow, any Lab Streaming Layer stream, a custom EEG board over USB serial or BLE, a generic serial device (one integer per line at 115200 baud), and file playback. The numbers below come from synthetic signals and recorded research EEG, not from a physical OpenBCI or Muse.
Software. A background thread fills a 10 s ring buffer, and each reading analyses the latest 2 s with a 60 Hz notch, a 1–45 Hz zero-phase Butterworth band-pass and a Welch PSD. The metrics use only theta, alpha and beta, because on consumer hardware delta is mostly drift and gamma is mostly muscle noise:
- focus = β/(α+θ), the Pope et al. (1995) engagement index
- calm = α/(α+β)
- attention = β/θ, the inverse theta/beta ratio (its diagnostic validity is contested, and the tool says so)
Every reading carries a confidence score and a status (ok, warming_up, unreliable). The language model never sees raw EEG. Instead, get_metric_definitions and get_pipeline_limitations give it the formulas, sources and caveats.

Real terminal output from bci-mcp devices and a one-shot stream on the synthetic device. Confidence is 0.15 on the first reading.
In 0.2.0 the FastMCP server exposes 14 tools, 2 resources and 1 prompt. Main adds a third resource, brain://citations, which isn't released yet. The same pipeline drives a CLI meter, a dashboard, a recorder and a neurofeedback trainer. Tool inputs are validated and capped, recordings are sandboxed, and playback:// and serial:// are refused over MCP.
Results
I ran the pipeline on the eyes-open and eyes-closed baselines of all 109 subjects in the PhysioNet EEG Motor Movement/Imagery Dataset (O1/Oz/O2, 2 s windows, uncalibrated). Calm rose with eyes closed in 105 of 109 subjects (median 0.39 to 0.65; Wilcoxon p = 3.2×10⁻¹⁹), which reproduces the classic Berger alpha effect. Within a subject, a single calm threshold separated the two conditions with a median AUC of 0.87. Pooled across subjects it was only 0.78, which shows why per-user calibration is there.

Calm and relative alpha rise with eyes closed in 105 of 109 PhysioNet subjects.
On synthetic signals, all six metrics were monotonic in the generator parameter (Spearman |ρ| = 0.996).

Synthetic sweep of focus, calm and fatigue against the synthetic generator's focus parameter (mean and error bars).
Per-window DSP took a median of 0.35 ms (4 channels at 256 Hz), and a get_brain_state call over stdio had a median...
Inky Ganbold