nimbus-mcp
MCP server that lets AI agents (Claude Code, Cursor, Claude Desktop) build, validate, run, and analyze Nimbus BCI pipelines — upload their own EEG data, persist pipelines into studio projects, run multi-configuration experiment campaigns, watch live EEG sessions, and (explicitly confirmed) start live streaming — through your local Nimbus backend.
Install
pip install nimbus-mcp # or: uvx nimbus-mcp
(Also installable from the repo: pip install -e nimbus-studio/mcp.)
Requirements
- A Nimbus backend running locally: the desktop app, or the dev server
(
cd nimbus-studio/backend-py && python -m nimbus_backend.server.app) withDEBUG=1. - The backend started with
MCP_LOCAL_KEY=<some-secret>(never set this on Fly — it is refused there). - Desktop app users: open Settings → MCP & Agents — no manual key setup (the app creates the key, injects it into its backend, and hands you copy-ready configs).
Configure the backend
Desktop/dev env (e.g. backend-py/data/.env or the dev shell):
MCP_LOCAL_KEY=choose-a-long-random-string
MCP_LOCAL_USER_ID=user_your_clerk_user_id
DEBUG=1 # dev server only; the desktop app qualifies automatically
MCP_LOCAL_USER_ID sets the principal the MCP key authenticates as. Set it to your
own Clerk user id (user_…) so everything the agent creates — projects, saved
pipelines, executions — appears in your studio UI as yours. Pick one owner and stick
with it: switching the id mid-life splits ownership of agent-created work across two
principals, and neither identity then sees the whole history.
Watchdog default: streaming sessions started through MCP are auto-stopped after
15 minutes with no one watching (every stream_status / get_live_session poll
resets the timer). Pass idle_timeout_sec=0 to start_stream to disable it for a
session.
When enabling MCP_LOCAL_KEY on a machine connected to an untrusted network, also set
HOST=127.0.0.1 on the backend. The 0.0.0.0 default (settings.host) applies to the
bare dev server (python -m nimbus_backend.server.app), so with it the key would
otherwise be accepted from the LAN; backend-py/scripts/run_server.py already defaults
to 127.0.0.1, and the desktop app pins loopback itself.
Run the server
cd nimbus-studio/mcp
python -m venv .venv && source .venv/bin/activate
pip install -e ".[test]"
NIMBUS_MCP_KEY=choose-a-long-random-string python -m nimbus_mcp
Env vars: NIMBUS_API_URL (default http://127.0.0.1:8080), NIMBUS_MCP_KEY
(must match MCP_LOCAL_KEY), NIMBUS_MCP_KEY_FILE (path to a 0600 JSON file
{"key": "…"} — the desktop app's one-click MCP setup writes it and its config
snippets reference it; consulted only when NIMBUS_MCP_KEY is unset),
NIMBUS_EXPORT_DIR (default ~/nimbus-exports).
Claude Code
# --env flags go BEFORE the -- separator (everything after it is the literal
# server command, so the after-form would feed --env to python/uvx):
claude mcp add nimbus --env NIMBUS_MCP_KEY=choose-a-long-random-string \
-- <path-to-mcp-venv>/bin/python -m nimbus_mcp
Cursor / Claude Desktop (stdio)
{
"mcpServers": {
"nimbus": {
"command": "<path-to-mcp-venv>/bin/python",
"args": ["-m", "nimbus_mcp"],
"env": { "NIMBUS_MCP_KEY": "choose-a-long-random-string" }
}
}
}
Tools (28)
Discovery: list_nodes, get_node_schema, list_templates, get_template, list_datasets
Data: upload_data
Build: validate_pipeline, validate_node_config
Run: run_pipeline (non-blocking), get_execution, list_executions, get_results, cancel_execution
Campaigns: run_experiment (non-blocking, 1-25 paced runs), get_experiment
Artifacts: list_artifacts, download_artifact, export_python
Live: list_devices, test_device, start_stream (needs confirm=true),
stream_status, get_live_session, stop_stream
Projects: create_project, list_projects, save_pipeline, load_pipeline
Uploading data
Bring your own recordings instead of (or alongside) the public datasets.
"I have a
.edfrecording at~/recordings/session-01.edf— upload it and build a pipeline around it."
The agent calls upload_data(file_path=…), which registers the file with the
backend and returns the stored path; that path goes into a custom_data node's
config ({"filePath": "<path>", "format": "edf", …}) for validate_pipeline /
run_pipeline / run_experiment.
Experiment campaigns
One run_experiment call = a paced sweep of 1-25 pipelines (at most 2 training
runs in flight) with aggregated metrics, instead of the agent babysitting 25
individual run_pipeline polls.
"Compare CSP-LDA vs EEGNet on BNCI2014_001 across subjects 1-3."
The agent builds six train graphs, calls
run_experiment(runs=[{name: "csp-lda-s1", train_graph: …}, …]), gets an
experimentId back immediately, then polls get_experiment(experiment_id) until
status is completed — per-run status and, at the end,
aggregates like {"kappa": {"mean": 0.61, "std": 0.08, "best": {name, value}}}
(mean/std/best over completed runs only).
Working with projects
Agent builds, human inspects. Pipelines the agent saves land in real studio projects, so you can open the canvas and see exactly what ran.
"Save this pipeline as a project called 'motor-imagery-baseline' — I'll review it in the studio."
create_project(name) makes the container, save_pipeline(project_id, train_graph) writes the graph (layout auto-generated, revision conflicts retried
once) and load_pipeline(project_id) reads it back for editing or re-running.
With MCP_LOCAL_USER_ID set to your user id, the project shows up in your
studio project list.
Watching a live session
While a streaming session runs, the agent can watch its telemetry and tell you what it sees.
"Watch my focus session and tell me when signal quality drops."
The agent polls get_live_session(session_id) — latest prediction, the recent
window, signal quality (meanChannelQuality, snrDb, artifactProbability) and
running stats — and warns when quality degrades. Each poll also resets the idle
watchdog, so a session under active watch is never auto-stopped; an abandoned one
is shut down after 15 minutes.
Safety
start_stream refuses to run without confirm=true — it connects an EEG device and
starts a live session on a human. The X-MCP-Key path is machine-local only
(never accepted on Fly deployments). Sessions started via MCP are stopped
automatically after 15 idle minutes (see the watchdog note above).
Metadata
Release files for nimbus-mcp 0.2.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| nimbus_mcp-0.2.1.tar.gz | 29.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| nimbus_mcp-0.2.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 55.4 kB
Release files / nimbus_mcp-0.2.1.tar.gz
| Download URL | nimbus_mcp-0.2.1.tar.gz |
|---|---|
| Size | 29.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
9fc67f7a05dced57cc6d071fd5d73068022ab379cbfc7563a80043442f4cddca
|
|
BLAKE2b-256 checksum How to use checksums |
4ff650f2b6ae4f0295c5326820ae9e31a888f0d04354941490731b29efd02f44
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.2
|
Release files / nimbus_mcp-0.2.1-py3-none-any.whl
| Download URL | nimbus_mcp-0.2.1-py3-none-any.whl |
|---|---|
| Size | 26.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
89342339d9bed46fa6c34a4943080eb52511ef9a442d69e20559c776222fe1db
|
|
BLAKE2b-256 checksum How to use checksums |
171514bc618470bc3da2a4ddd1fb5a40e0dce7c8144d0af5f192479c1d6dffad
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.2
|