Nimbus BCI MCP
An MCP server enabling AI agents to build, validate, run, and analyze EEG/BCI pipelines. It supports uploading EEG data, persisting pipelines to studio projects, running experiment campaigns on public datasets like MOABB/BNCI, rendering plots, and exporting BIDS formats via a hosted backend or local deployment.
Endpoint and access
No sign-in to connect and list tools. Individual tools may still need a vendor account, credentials, or permissions; check the documented prerequisites.
https://nimbus-mcp.fly.dev/mcpWhat its tools do
63 tools, grouped by the hints the server advertises. Hints are self-declared, not verified behavior.
Read-only (32)
account.whoamicatalog.nodescatalog.node_schemacatalog.templatescatalog.templatecatalog.datasetscatalog.leaderboardleaderboard.statusleaderboard.minepipeline.validatepipeline.validate_nodeexecution.getexecution.listexecution.resultscalibration.statusexperiment.getexecution.artifactsdevice.listdevice.teststream.statusstream.telemetrydata.inspect_datasetdata.inspect_fileproject.listproject.loadprotocol.validateprotocol.listprotocol.session_statusprotocol.export_statspython.validatestats.groupedfoundation.compare
Can change data (31)
leaderboard.submitexecution.runexecution.cancelexecution.deletecalibration.startcalibration.pausecalibration.resumecalibration.trainexperiment.runexperiment.deleteexecution.download_artifactpipeline.exportbids.export_datasetbids.export_executionstream.startstream.stopplots.confusionplots.datasetplots.erpplots.leaderboarddata.uploaddata.delete_uploadproject.createproject.saveproject.renameproject.deleteprotocol.saveprotocol.start_assignmentprotocol.pauseprotocol.resumeprotocol.stop
Checks and signals
Each line is separate evidence, not a trust score.
- Passed Endpoint answered the live check ·
- Availability 1 of 1 checks passed in 30 days
What you can do with it
- Build and validate EEG/BCI pipelines
- Run experiment campaigns on public datasets
- Analyze results and render plots
- Export data in BIDS format
Source and maintenance
- Maintenance checked
Protocol and capabilities
- Server
- nimbus 0.14.21
- MCP protocol negotiated in check
- 2025-11-25
- Tools
- 63 advertised
- Resources
- 0 advertised
- Resource templates
- 0 advertised
- Prompts
- 5 advertised
{
"tools": {
"listChanged": true
},
"logging": {},
"prompts": {
"listChanged": true
},
"resources": {
"subscribe": false,
"listChanged": true
}
}Server-provided instructions
Untrusted server output shown for inspection. It is not Koskamo guidance and is excluded from knowledge search.
Tools
63 advertised
account.whoami — Who Am I
Who you are authenticated as: account email, plan (isPro / pioneer), this month's free-run quota, and — with a hosted token — the token name and days until it expires. Call this first when setup guidance appears or to check which credential a session uses. In anonymous Local Free mode there is no account: the response says so (mode/tier) instead of demanding a login.
{
"type": "object",
"properties": {},
"additionalProperties": false
}{
"type": "object",
"additionalProperties": true
}{
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}catalog.nodes — List Pipeline Nodes
List Nimbus pipeline node types (data, preprocessing, features, models...). Use catalog.node_schema(node_type) for one node's full config schema and ports.
{
"type": "object",
"properties": {
"category": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Optional filter by category id — e.g. \"data\",\n\"preprocessing\", \"feature\", \"model\" (singular ids; plurals such\nas \"models\"/\"features\" are accepted). An unknown category is an\nerror that lists the valid ids."
}
},
"additionalProperties": false
}{
"type": "object",
"additionalProperties": true
}{
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}catalog.node_schema — Node Config Schema
Full config JSON schema + input/output ports for one node type.
{
"type": "object",
"required": [
"node_type"
],
"properties": {
"node_type": {
"type": "string",
"description": "Node id from catalog.nodes (e.g. \"csp\", \"nimbus_lda\")."
}
},
"additionalProperties": false
}{
"type": "object",
"additionalProperties": true
}{
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}catalog.templates — List Pipeline Templates
List built-in starter pipelines (MI/P300/SSVEP...). catalog.template(id) returns the graph. Each row carries ``datasetId`` (catalog id, e.g. "BNCI2014_001" — the id catalog.leaderboard and catalog.datasets use) and ``paradigm`` when the template loads a public dataset.
{
"type": "object",
"properties": {
"dataset": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Only templates on this dataset id (e.g. \"BNCI2014_001\"); case-insensitive."
},
"paradigm": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Only templates with this paradigm (e.g. \"motor_imagery\", \"p300\", \"ssvep\")."
}
},
"additionalProperties": false
}{
"type": "object",
"additionalProperties": true
}{
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}catalog.template — Get Pipeline Template
Full template incl. the 'train' execGraph needed by execution.run/pipeline.validate.
{
"type": "object",
"required": [
"template_id"
],
"properties": {
"template_id": {
"type": "string",
"description": "Template id from catalog.templates (e.g. \"mi_csp_lda\")."
}
},
"additionalProperties": false
}{
"type": "object",
"additionalProperties": true
}{
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}catalog.datasets — List Datasets
Curated public EEG datasets (MOABB packs) available to pipelines.
{
"type": "object",
"properties": {
"only_on_disk": {
"type": "boolean",
"default": true,
"description": "Only return datasets whose data packs are present on this\nbackend (True by default; False also lists known-but-missing sets)."
}
},
"additionalProperties": false
}{
"type": "object",
"additionalProperties": true
}{
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}catalog.leaderboard — Leaderboard
Public benchmark leaderboard: pipeline rankings per dataset. Two tracks: the top-level ``within_session`` block (curated suite pipelines) and ``crossSubject`` (leave-one-subject-out — curated pipelines plus BYO ``python_model`` submissions; BYO rows carry ``kind: "byo"`` and an ``owner`` name). Within each dataset, ``rows`` sort desc by ``meanAccuracyPct`` (95% CI in ``ciLoPct``/``ciHiPct``). ``packFingerprint`` identifies the exact dataset pack behind the scores; ``updated`` marks each dataset's most recent run. The ``pretrainedFewTrial`` efficiency track means: accuracy at a protocol-fixed 100-trials-per-subject budget — the frozen-backbone / few-parameter rows that matter when calibration data is scarce (``paramsTrained`` shown per row so cost is readable next to accuracy). ``submittableDatasets`` is the set open for ``leaderboard.submit``; a dataset can appear under ``crossSubject`` and still be closed for new submissions.
{
"type": "object",
"properties": {
"dataset_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Optional dataset id. When set, every track is filtered\nto that dataset. Omit it for the full board."
}
},
"additionalProperties": false
}{
"type": "object",
"additionalProperties": true
}{
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}leaderboard.submit — Submit to Leaderboard
Submit a BYO python_model to a leaderboard track for server-side scoring. Nimbus scores it server-side under the track's fixed protocol — you submit code, never results. Poll ``leaderboard.status`` with the returned ``submissionId``; scoring takes minutes (classical) to tens of minutes (deep). Requirements must be plain PyPI names/specs (max 20, no URLs). Identical code resubmission is idempotent per track (``deduplicated: true``). Verification contract (tier model X10): ``verification="verified"`` (default) is the server-side-scored submission above — on the hosted backend it is Pro-only; free accounts get a structured tier response. ``verification="unverified_local"`` names the designed Account-Free lane for locally-computed results; the backend has no unverified submission kind yet (see the response it returns — nothing is stored, and no row is faked). Anonymous callers get a structured login prompt: a submission needs an identity. Local (desktop/dev) backends keep their existing server-side quota behaviour.
{
"type": "object",
"required": [
"dataset_id",
"name"
],
"properties": {
"code": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Python source defining a class with fit(X, y, info) and\npredict(X) (<=256KB; validate first with python.validate).\nRequired unless backbone_repo is set."
},
"name": {
"type": "string",
"description": "Display name on the board (<=100 chars)."
},
"track": {
"enum": [
"cross_subject",
"pretrained_few_trial"
],
"type": "string",
"default": "cross_subject",
"description": "\"cross_subject\" (default — full-data leave-one-subject-out,\nseed 42) or \"pretrained_few_trial\" (efficiency track: LOSO with\na protocol-fixed 100-trials-per-subject cap; code that imports\ntorch must declare its trained parameter count as a class\nattribute — PARAMS_TRAINED = <int> — which becomes the row's\nparamsTrained and is cross-checked when computable)."
},
"class_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Contract class to instantiate; omit to auto-detect."
},
"dataset_id": {
"type": "string",
"description": "A dataset id from catalog.leaderboard\n``submittableDatasets`` (e.g. \"BNCI2014_001\"). A dataset can\nappear under crossSubject and still be closed for submission\n(BNCI2014_008 is scored there and is not in the open set)."
},
"requirements": {
"anyOf": [
{
"type": "array",
"items": {
"type": "string"
}
},
{
"type": "null"
}
],
"default": null,
"description": "Optional PyPI requirements (e.g. [\"sklearn>=1.4\"])."
},
"verification": {
"enum": [
"verified",
"unverified_local"
],
"type": "string",
"default": "verified",
"description": "\"verified\" (default; server-side scored, Pro on\nthe hosted backend) or \"unverified_local\" (Account-Free\nlocally-computed lane; see the tool description for its\ncurrent backend status)."
},
"backbone_kind": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Checkpoint family for the BYO backbone lane — one\nof the zoo's supported kinds (e.g. \"cbramod\", \"labram\")."
},
"backbone_repo": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "HF 'org/name' repo id for the BYO backbone lane."
},
"backbone_license": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "License declared for the backbone checkpoint."
},
"backbone_revision": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Full 40-char commit SHA pinning the backbone."
}
},
"additionalProperties": false
}{
"type": "object",
"additionalProperties": true
}{
"readOnlyHint": false,
"openWorldHint": true,
"idempotentHint": false,
"destructiveHint": false
}leaderboard.status — Leaderboard Submission Status
Fetch one of your leaderboard submissions (owner-only). Returns status (queued | scoring | done | failed), metrics when done (meanAccuracyPct + CI, same shape as leaderboard rows), or the error that failed it.
{
"type": "object",
"required": [
"submission_id"
],
"properties": {
"submission_id": {
"type": "string",
"description": "The submissionId returned by leaderboard.submit."
}
},
"additionalProperties": false
}{
"type": "object",
"additionalProperties": true
}{
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}leaderboard.mine — My Leaderboard Submissions
List your leaderboard submissions (newest first), all datasets.
{
"type": "object",
"properties": {},
"additionalProperties": false
}{
"type": "object",
"additionalProperties": true
}{
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}pipeline.validate — Validate Pipeline
Validate a pipeline graph before running. ExecGraphSnapshot: {nodes: [{id, type, config}], connections: [{from, to}]}. Build it from catalog.template(id).train or from scratch using catalog.nodes().
{
"type": "object",
"required": [
"train_graph"
],
"properties": {
"train_graph": {
"type": "object",
"description": "The graph to validate ({nodes, connections}).",
"additionalProperties": true
}
},
"additionalProperties": false
}{
"type": "object",
"additionalProperties": true
}{
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}pipeline.validate_node — Validate Node Config
Validate one node's config (schema + semantic checks). Catches the same value errors as pipeline.validate for a single node (inverted bandpass, CSP components vs channel count when dataset is set).
{
"type": "object",
"required": [
"node_type",
"config"
],
"properties": {
"config": {
"type": "object",
"description": "The node's config object to check.",
"additionalProperties": true
},
"dataset": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Optional MOABB pack id (e.g. \"BNCI2014_001\") so CSP/Nyquist\nchecks can use channel count and sampling rate. Omitted → those\ncontext checks are skipped; inverted-band checks still run."
},
"node_type": {
"type": "string",
"description": "Node type id from catalog.nodes (e.g. \"csp\", \"bandpass_filter\")."
}
},
"additionalProperties": false
}{
"type": "object",
"additionalProperties": true
}{
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}execution.run — Run Pipeline
Start a pipeline run (NON-BLOCKING). Returns executionId — poll with execution.get() until status is completed/failed, then execution.results(). If an identical graph is already running for you, the run still starts but the response carries a ``warning`` + ``duplicateOf`` ids (cancel one with execution.cancel to avoid paying twice). The server runs a limited number of executions at once (3 by default); when all slots are busy the call fails immediately with 429 nimbus.execution.queue_full and a retryAfter (seconds) — wait, then retry.
{
"type": "object",
"required": [
"train_graph"
],
"properties": {
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Display name for the run (shown in the Runs list)."
},
"layout": {
"anyOf": [
{
"type": "object",
"additionalProperties": true
},
{
"type": "null"
}
],
"default": null,
"description": "Optional canvas positions {nodes: {id: {x, y}}}; a deterministic\ngrid is synthesized when omitted."
},
"subject": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Optional dataset subject code (e.g. \"S01\") recorded with the run."
},
"description": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Optional longer description of the experiment."
},
"train_graph": {
"type": "object",
"description": "Pipeline graph {nodes: [{id, type, config}], connections:\n[{from, to}]} as built by catalog.template/pipeline.validate.",
"additionalProperties": true
}
},
"additionalProperties": false
}{
"type": "object",
"additionalProperties": true
}{
"readOnlyHint": false,
"openWorldHint": true,
"idempotentHint": false,
"destructiveHint": false
}execution.cancel — Cancel Run
Cancel a running execution.
{
"type": "object",
"required": [
"execution_id"
],
"properties": {
"execution_id": {
"type": "string",
"description": "The run to terminate (from execution.run/execution.list)."
}
},
"additionalProperties": false
}{
"type": "object",
"additionalProperties": true
}{
"readOnlyHint": false,
"openWorldHint": true,
"idempotentHint": false,
"destructiveHint": true
}execution.delete — Delete Run
Permanently delete one of your finished runs (completed/failed/cancelled) with its results. Running runs must be cancelled first (409 nimbus.execution.delete_not_terminal). Owner only.
{
"type": "object",
"required": [
"execution_id"
],
"properties": {
"confirm": {
"type": "boolean",
"default": false,
"description": "MUST be true to delete — the explicit user go-ahead."
},
"execution_id": {
"type": "string",
"description": "The run to delete (from execution.run/execution.list)."
}
},
"additionalProperties": false
}{
"type": "object",
"additionalProperties": true
}{
"readOnlyHint": false,
"openWorldHint": true,
"idempotentHint": false,
"destructiveHint": true
}execution.get — Get Run
Execution status summary (status: running/completed/failed/cancelled). Summary fields: ``dataset`` is the human-readable display label (e.g. "BCIIV2a"); ``datasetId`` is the catalog id (e.g. "BNCI2014_001") accepted by other tools (data.inspect_dataset, public_data.dataset). ``title`` is the run name shown in Studio.
{
"type": "object",
"required": [
"execution_id"
],
"properties": {
"execution_id": {
"type": "string",
"description": "The run to check (from execution.run/execution.list)."
}
},
"additionalProperties": false
}{
"type": "object",
"additionalProperties": true
}{
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}execution.list — List Runs
Recent executions. Optional status filter (running/completed/failed/cancelled). Per-run fields: ``dataset`` is the human-readable display label (e.g. "BCIIV2a"); ``datasetId`` is the catalog id (e.g. "BNCI2014_001") accepted by other tools (data.inspect_dataset, public_data.dataset). ``title`` is the run name shown in Studio.
{
"type": "object",
"properties": {
"limit": {
"type": "integer",
"default": 20,
"description": "Maximum number of runs to return (default 20)."
},
"status": {
"enum": [
"running",
"completed",
"failed",
"cancelled",
null
],
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Filter by run status: running/completed/failed/cancelled."
}
},
"additionalProperties": false
}{
"type": "object",
"additionalProperties": true
}{
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}execution.results — Run Results
Metrics for a completed run. Trimmed by default (accuracy, kappa, ITR, confusion matrix, per-class); full=True returns the complete result object.
{
"type": "object",
"required": [
"execution_id"
],
"properties": {
"full": {
"type": "boolean",
"default": false,
"description": "Return the backend's complete result object (all fields)."
},
"execution_id": {
"type": "string",
"description": "The completed run to fetch metrics for."
}
},
"additionalProperties": false
}{
"type": "object",
"additionalProperties": true
}{
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}calibration.start — Start Calibration
Start a guided subject calibration session (NON-BLOCKING; confirm-gated — the device goes on a human's head). The Nimbus Studio app shows the cues on its calibration dashboard automatically; poll calibration.status. Requires a Pro plan (hosted token or Pro session): calibration nodes and custom-data training are gated by the freemium node policy; local X-MCP-Key principals pass only when the desktop app flags the signed-in Pro session (MCP_LOCAL_IS_PRO).
{
"type": "object",
"properties": {
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Display name recorded on the execution."
},
"port": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Serial/COM port for wired devices."
},
"classes": {
"anyOf": [
{
"type": "array",
"items": {
"type": "object",
"additionalProperties": true
}
},
{
"type": "null"
}
],
"default": null,
"description": "Override class list [{id,label,cue}] (MI default: left/right hand)."
},
"confirm": {
"type": "boolean",
"default": false,
"description": "MUST be true — explicit user go-ahead for a session on their head."
},
"ip_port": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"description": "Port for network devices."
},
"paradigm": {
"type": "string",
"default": "mi",
"description": "mi | p300 | sart | target_hit."
},
"source_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "LSL source id."
},
"ip_address": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Device IP for network/wifi devices."
},
"device_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Device id from device.list (omit → template default synthetic)."
},
"mac_address": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Bluetooth MAC (BT devices)."
},
"stream_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "LSL stream name (LSL devices)."
},
"serial_number": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Device serial (some BLE stacks)."
},
"connection_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Device selector when several exist (e.g. serial vs wifi)."
},
"trials_per_class": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"description": "Override the template's trial count (minimum 5)."
}
},
"additionalProperties": false
}{
"type": "object",
"additionalProperties": true
}{
"readOnlyHint": false,
"openWorldHint": true,
"idempotentHint": false,
"destructiveHint": false
}calibration.status — Calibration Status
Live snapshot of a calibration session (phase, current trial, progress, paused). Once complete, carries the recorded upload — call calibration.train to turn it into the subject's own classifier.
{
"type": "object",
"required": [
"execution_id"
],
"properties": {
"execution_id": {
"type": "string",
"description": "The calibration run to inspect (from calibration.start)."
}
},
"additionalProperties": false
}{
"type": "object",
"additionalProperties": true
}{
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}calibration.pause — Pause Calibration
Pause a running calibration between trials (cues hold; resume anytime).
{
"type": "object",
"required": [
"execution_id"
],
"properties": {
"execution_id": {
"type": "string",
"description": "The calibration run to pause."
}
},
"additionalProperties": false
}{
"type": "object",
"additionalProperties": true
}{
"readOnlyHint": false,
"openWorldHint": true,
"idempotentHint": false,
"destructiveHint": false
}calibration.resume — Resume Calibration
Resume a paused calibration session.
{
"type": "object",
"required": [
"execution_id"
],
"properties": {
"execution_id": {
"type": "string",
"description": "The calibration run to resume."
}
},
"additionalProperties": false
}{
"type": "object",
"additionalProperties": true
}{
"readOnlyHint": false,
"openWorldHint": true,
"idempotentHint": false,
"destructiveHint": false
}calibration.train — Train Calibration Model
Train the subject's own classifier from a COMPLETED calibration session (NON-BLOCKING). Fetches the recorded upload, wires it into a train pipeline as a custom_data source, and starts the run. Requires a Pro plan (custom_data training is freemium-gated). The calibrate→train handoff resolves on every backend, desktop-local included; only recordings made before the desktop execution-linkage build resolve no upload — rerun calibration.start for those.
{
"type": "object",
"required": [
"execution_id"
],
"properties": {
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Display name recorded on the training run."
},
"paradigm": {
"type": "string",
"default": "mi",
"description": "Paradigm of the recording (mi | p300 | sart | target_hit);\nmi and p300 have default train templates."
},
"template_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Train template to use (e.g. from catalog.templates);\nrequired for sart/target_hit (mi defaults to mi_headband_csp_lda,\np300 to p300_hardware_xdawn_lda)."
},
"train_graph": {
"anyOf": [
{
"type": "object",
"additionalProperties": true
},
{
"type": "null"
}
],
"default": null,
"description": "Explicit train graph instead of a template; its first\ndata node (custom_data/public_data) is rewired onto the recording."
},
"execution_id": {
"type": "string",
"description": "The COMPLETED calibration run (from calibration.start)."
}
},
"additionalProperties": false
}{
"type": "object",
"additionalProperties": true
}{
"readOnlyHint": false,
"openWorldHint": true,
"idempotentHint": false,
"destructiveHint": false
}experiment.run — Run Experiment
Run 1-25 pipelines as ONE paced experiment (NON-BLOCKING). Returns an experimentId immediately; a background thread submits at most 2 runs at a time (min(max_concurrent, 2)), retries queue-full up to 3 times per run, and polls each execution to completion. Poll experiment.get() for per-run status and, once finished, aggregated metrics. PORTABILITY: the experiment record is written through to the Nimbus server under your account (at start and at completion), so experiment.get works from ANY entry point — local stdio, hosted gateway, another machine — signed in with the same account/token. If the server is unreachable when the experiment starts it still runs and polls locally, but other entry points cannot read it until a write-through succeeds (#518).
{
"type": "object",
"required": [
"runs"
],
"properties": {
"runs": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": true
},
"description": "1-25 entries, each {name: str, train_graph: {nodes, connections}}\n(same graph shape as execution.run's train_graph)."
},
"max_concurrent": {
"type": "integer",
"default": 2,
"description": "Parallel submissions cap, clamped to 1-2 (default 2)."
}
},
"additionalProperties": false
}{
"type": "object",
"additionalProperties": true
}{
"readOnlyHint": false,
"openWorldHint": true,
"idempotentHint": false,
"destructiveHint": false
}experiment.delete — Delete Experiment
Delete one of your experiment records (server + this machine's local cache). Its individual runs are kept — delete them with execution.delete. A still-running experiment cannot be deleted.
{
"type": "object",
"required": [
"experiment_id"
],
"properties": {
"confirm": {
"type": "boolean",
"default": false,
"description": "MUST be true to delete — the explicit user go-ahead."
},
"experiment_id": {
"type": "string",
"description": "The experiment to delete (from experiment.run)."
}
},
"additionalProperties": false
}{
"type": "object",
"additionalProperties": true
}{
"readOnlyHint": false,
"openWorldHint": true,
"idempotentHint": false,
"destructiveHint": true
}experiment.get — Get Experiment
Experiment snapshot: status (running/completed/failed), per-run rows ({name, executionId, status, error?, metrics?, evaluationKind?}) and, once finished, aggregates over completed runs only: per-metric {mean, std, best, n}, plus ``pooledExecutionIds`` / ``pooledRunNames`` / ``kindBreakdown`` (per-subject vs LOSO etc. — each row has kind, n, mean, std, executionIds, runNames; #470). Pooled headline means are unchanged; kindBreakdown labels what was pooled. std is population; None below 2 values. kindBreakdown is always present when aggregates exist (including single-kind experiments). PORTABILITY: experiment records are stored on the Nimbus server under your account, so any entry point (local stdio, hosted gateway, another machine) signed in with the same account/token can read them; the serving process and the local ~/.nimbus/experiments store remain as fast-path caches. Experiments run before server-side storage landed exist only in the origin machine's local store and read as unknown elsewhere (#518).
{
"type": "object",
"required": [
"experiment_id"
],
"properties": {
"experiment_id": {
"type": "string",
"description": "The experiment to inspect (from experiment.run)."
}
},
"additionalProperties": false
}{
"type": "object",
"additionalProperties": true
}{
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}execution.artifacts — List Run Artifacts
Trained artifacts (models/filters, e.g. *.pkl) saved by an execution.
{
"type": "object",
"required": [
"execution_id"
],
"properties": {
"execution_id": {
"type": "string",
"description": "Run whose artifacts to list."
}
},
"additionalProperties": false
}{
"type": "object",
"additionalProperties": true
}{
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}execution.download_artifact — Download Run Artifact
Download one artifact file. Local/stdio: saved to NIMBUS_EXPORT_DIR/executions/<id>/ and its path returned. Hosted gateway: returned inline as ``contentBase64`` (up to 1 MB of base64); larger files point to Nimbus Studio. Nothing is written on the gateway.
{
"type": "object",
"required": [
"execution_id",
"artifact_name"
],
"properties": {
"execution_id": {
"type": "string",
"description": "Run that produced the artifact."
},
"artifact_name": {
"type": "string",
"description": "File name from execution.artifacts (e.g. \"nimbus_lda.pkl\")."
}
},
"additionalProperties": false
}{
"type": "object",
"additionalProperties": true
}{
"readOnlyHint": false,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}pipeline.export — Export Pipeline
Export the pipeline as a standalone runnable Python bundle (zip). Local/stdio: the zip is saved under NIMBUS_EXPORT_DIR/exports and its path returned. Hosted gateway: the zip is returned inline as ``contentBase64`` (up to 1 MB of base64). UI-only nodes (interactive_application) are left out and listed in ``exportNotes``.
{
"type": "object",
"required": [
"train_graph"
],
"properties": {
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Optional name recorded inside the bundle."
},
"train_graph": {
"type": "object",
"description": "Pipeline graph {nodes, connections} to export.",
"additionalProperties": true
}
},
"additionalProperties": false
}{
"type": "object",
"additionalProperties": true
}{
"readOnlyHint": false,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}bids.export_dataset — Export Dataset as BIDS
Export a Nimbus dataset as a BIDS-layout zip (local: saved to NIMBUS_EXPORT_DIR/bids/; hosted gateway: inline ``contentBase64``, up to 1 MB). Continuous sources (EDF/BDF uploads, stream recordings) export as BIDS-raw (EDF byte-passthrough; recordings converted HDF5→EDF with events.tsv). Epoched sources (MOABB packs, trial-table uploads) export as BIDS-derivatives (data passthrough + descriptive trial_index/label/session/run events — no fabricated onsets). The zip embeds nimbus_export_manifest.json with sha256s.
{
"type": "object",
"required": [
"dataset"
],
"properties": {
"kind": {
"enum": [
"auto",
"pack",
"upload",
"recording",
null
],
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Optional explicit source kind: pack|upload|recording (default auto)."
},
"dataset": {
"type": "string",
"description": "Dataset id — a MOABB pack id (e.g. \"BNCI2014_001\"), an upload\npath (as returned by data.upload), or a recording name. Auto-detected."
},
"subjects": {
"anyOf": [
{
"type": "array",
"items": {
"type": "string"
}
},
{
"type": "null"
}
],
"default": null,
"description": "Pack exports only — subject filter (e.g. [\"S01\", \"S03\"]) to\nbound zip size; default exports all installed subjects."
}
},
"additionalProperties": false
}{
"type": "object",
"additionalProperties": true
}{
"readOnlyHint": false,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}bids.export_execution — Export Run as BIDS
Export an execution's results as a BIDS-derivative zip (metrics.json, per-subject participants.tsv, protocol.json, full pipeline_snapshot.json, predictions.tsv when stored, provenance/execution.json). Local: saved to NIMBUS_EXPORT_DIR/bids/. Hosted gateway: inline ``contentBase64`` (up to 1 MB of base64); larger zips point to Nimbus Studio.
{
"type": "object",
"required": [
"execution_id"
],
"properties": {
"execution_id": {
"type": "string",
"description": "Run whose results to export (from execution.run)."
}
},
"additionalProperties": false
}{
"type": "object",
"additionalProperties": true
}{
"readOnlyHint": false,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}device.list — List EEG Devices
EEG devices supported by this backend (OpenBCI, Muse, BrainBit, LSL, PiEEG...).
{
"type": "object",
"properties": {},
"additionalProperties": false
}{
"type": "object",
"additionalProperties": true
}{
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}device.test — Test EEG Device
Test a device connection WITHOUT starting a stream (safe, no confirm needed).
{
"type": "object",
"required": [
"device_type"
],
"properties": {
"port": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Serial/COM port for wired devices."
},
"ip_port": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"description": "Port for network devices."
},
"source_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "LSL source id."
},
"ip_address": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Device IP for network/wifi devices."
},
"device_type": {
"type": "string",
"description": "Device id from device.list (e.g. \"brainbit\", \"muse\")."
},
"mac_address": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Bluetooth MAC (BT devices)."
},
"stream_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "LSL stream name (LSL devices)."
},
"serial_number": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Device serial (some BLE stacks)."
},
"connection_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Device-specific selector when several exist (e.g. serial vs wifi)."
}
},
"additionalProperties": false
}{
"type": "object",
"additionalProperties": true
}{
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}stream.start — Start EEG Stream
Connect an EEG device and START a live streaming session on the user's head. Requires confirm=True; call device.test first. Track with stream.status(). Idle watchdog: if no stream.status()/stream.telemetry() poll happens for idle_timeout_sec (default 900), the session is stopped and the device disconnected automatically — an abandoned stream never keeps running on the user's head. Any poll resets the timer; idle_timeout_sec=0 disables the watchdog.
{
"type": "object",
"required": [
"device_type"
],
"properties": {
"port": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Serial/COM port for wired devices."
},
"confirm": {
"type": "boolean",
"default": false,
"description": "MUST be true to start — the explicit user go-ahead for a live\nsession on their head; anything else is refused with zero requests."
},
"ip_port": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"description": "Port for network devices."
},
"source_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "LSL source id."
},
"chunk_size": {
"type": "integer",
"default": 125,
"description": "Samples per streamed chunk (default 125)."
},
"ip_address": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Device IP for network/wifi devices."
},
"n_channels": {
"type": "integer",
"default": 8,
"description": "Channel count to open (default 8)."
},
"session_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Optional existing session to resume/reuse."
},
"device_type": {
"type": "string",
"description": "Device id from device.list (e.g. \"brainbit\")."
},
"mac_address": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Bluetooth MAC (BT devices)."
},
"stream_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "LSL stream name (LSL devices)."
},
"serial_number": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Device serial (some BLE stacks)."
},
"connection_type": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Device-specific selector (e.g. serial vs wifi)."
},
"idle_timeout_sec": {
"type": "integer",
"default": 900,
"description": "Watchdog: stop+disconnect after this many seconds\nwithout a status poll (default 900; 0 disables)."
}
},
"additionalProperties": false
}{
"type": "object",
"additionalProperties": true
}{
"readOnlyHint": false,
"openWorldHint": true,
"idempotentHint": false,
"destructiveHint": false
}stream.status — EEG Stream Status
Live snapshot of a streaming session (running, deviceConnected). Polling this also feeds the idle watchdog: each call resets the session's idle timer (see stream.start's idle_timeout_sec).
{
"type": "object",
"required": [
"session_id"
],
"properties": {
"session_id": {
"type": "string",
"description": "The streaming session to inspect."
}
},
"additionalProperties": false
}{
"type": "object",
"additionalProperties": true
}{
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}stream.stop — Stop EEG Stream
Stop a streaming session and disconnect the device (always safe to call). Also removes the session from the idle watchdog so it cannot fire after an explicit stop.
{
"type": "object",
"required": [
"session_id"
],
"properties": {
"session_id": {
"type": "string",
"description": "The streaming session to stop."
}
},
"additionalProperties": false
}{
"type": "object",
"additionalProperties": true
}{
"readOnlyHint": false,
"openWorldHint": true,
"idempotentHint": false,
"destructiveHint": true
}plots.confusion — Plot Confusion Matrix
Confusion-matrix figure for one execution: heatmap with trial counts + per-class accuracy bars, rendered as a PNG the assistant can see. Use it right after execution.results to eyeball WHICH classes are confused, not just the accuracy number.
{
"type": "object",
"required": [
"execution_id"
],
"properties": {
"save": {
"type": "boolean",
"default": false,
"description": "Local/stdio: also write the PNG to NIMBUS_EXPORT_DIR/plots/ and return\nits path. Ignored on the hosted gateway (the image is returned inline)."
},
"matrix": {
"type": "string",
"default": "eval",
"description": "\"eval\" (held-out, default) or \"train\" (fit-set / cross-validation).\nCV and evaluation-plan runs often have no eval matrix — use \"train\"."
},
"execution_id": {
"type": "string",
"description": "Run to plot (from execution.run / execution.results)."
}
},
"additionalProperties": false
}{
"type": "object",
"required": [
"ok"
],
"properties": {
"ok": {
"type": "boolean"
},
"meta": {
"type": "object",
"description": "Figure sidecar. foundation.compare includes results/best/skipped (also as a JSON text content block).",
"additionalProperties": true
},
"title": {
"type": [
"string",
"null"
]
},
"mimeType": {
"type": "string"
},
"savedPath": {
"type": "string",
"description": "Set when save=true."
},
"sizeBytes": {
"type": "integer",
"description": "Set when save=true."
}
}
}{
"readOnlyHint": false,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}plots.dataset — Plot Dataset
Figure over an EEG data source — the visual companion to data.inspect_dataset. kind=psd (Welch, channel mean bold), kind=bandpower (channel × band dB heatmap), kind=topomap (band-power scalp map), kind=spectrogram (time-frequency for one channel). Sources are the same ones inspect uses: MOABB packs, uploads, local files.
{
"type": "object",
"required": [
"kind",
"source"
],
"properties": {
"band": {
"enum": [
"delta",
"theta",
"alpha",
"beta",
"gamma"
],
"type": "string",
"default": "alpha",
"description": "Band for kind=topomap: delta|theta|alpha|beta|gamma (default alpha)."
},
"kind": {
"enum": [
"psd",
"topomap",
"bandpower",
"spectrogram"
],
"type": "string",
"description": "Figure type: psd | topomap | bandpower | spectrogram."
},
"mode": {
"enum": [
"training",
"evaluation",
"all"
],
"type": "string",
"default": "all",
"description": "Pack split to load: training | evaluation | all (source=dataset)."
},
"path": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Upload path (source=upload) or absolute local path (source=local)."
},
"save": {
"type": "boolean",
"default": false,
"description": "Local/stdio: also write the PNG to NIMBUS_EXPORT_DIR/plots/ and return\nits path. Ignored on the hosted gateway (the image is returned inline)."
},
"source": {
"enum": [
"dataset",
"upload",
"local"
],
"type": "string",
"description": "\"dataset\" (MOABB pack), \"upload\" (path from data.upload), or\n\"local\" (absolute path, local backend only)."
},
"dataset": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "MOABB dataset id, e.g. \"BNCI2014_001\" (source=dataset)."
},
"subject": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Subject id, e.g. \"S01\" (source=dataset)."
},
"channel_idx": {
"type": "integer",
"default": 0,
"description": "0-based channel for kind=spectrogram (default 0)."
}
},
"additionalProperties": false
}{
"type": "object",
"required": [
"ok"
],
"properties": {
"ok": {
"type": "boolean"
},
"meta": {
"type": "object",
"description": "Figure sidecar. foundation.compare includes results/best/skipped (also as a JSON text content block).",
"additionalProperties": true
},
"title": {
"type": [
"string",
"null"
]
},
"mimeType": {
"type": "string"
},
"savedPath": {
"type": "string",
"description": "Set when save=true."
},
"sizeBytes": {
"type": "integer",
"description": "Set when save=true."
}
}
}{
"readOnlyHint": false,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}plots.erp — Plot ERP
ERP butterfly figure from epoched data: one subplot per class, all channel means (thin) + across-channel mean (bold), time-locked to the trial event. Shows whether class-conditioned evoked structure exists BEFORE training anything.
{
"type": "object",
"required": [
"source"
],
"properties": {
"mode": {
"enum": [
"training",
"evaluation",
"all"
],
"type": "string",
"default": "all",
"description": "Pack split to load: training | evaluation | all (source=dataset)."
},
"path": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Upload path (source=upload) or absolute local path (source=local)."
},
"save": {
"type": "boolean",
"default": false,
"description": "Local/stdio: also write the PNG to NIMBUS_EXPORT_DIR/plots/ and return\nits path. Ignored on the hosted gateway (the image is returned inline)."
},
"source": {
"enum": [
"dataset",
"upload",
"local"
],
"type": "string",
"description": "\"dataset\" (MOABB pack), \"upload\" (path from data.upload), or\n\"local\" (absolute path, local backend only)."
},
"dataset": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "MOABB dataset id, e.g. \"BNCI2014_001\" (source=dataset)."
},
"subject": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Subject id, e.g. \"S01\" (source=dataset)."
},
"max_channels": {
"type": "integer",
"default": 16,
"description": "Channels drawn per class subplot (default 16, max 64)."
}
},
"additionalProperties": false
}{
"type": "object",
"required": [
"ok"
],
"properties": {
"ok": {
"type": "boolean"
},
"meta": {
"type": "object",
"description": "Figure sidecar. foundation.compare includes results/best/skipped (also as a JSON text content block).",
"additionalProperties": true
},
"title": {
"type": [
"string",
"null"
]
},
"mimeType": {
"type": "string"
},
"savedPath": {
"type": "string",
"description": "Set when save=true."
},
"sizeBytes": {
"type": "integer",
"description": "Set when save=true."
}
}
}{
"readOnlyHint": false,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}plots.leaderboard — Plot Leaderboard
Leaderboard bar chart for one dataset: accuracy with 95% CI whiskers, best first; BYO python_model submissions highlighted in a distinct color. The visual companion to catalog.leaderboard. On the pretrained_few_trial track the figure also includes the classical LOSO baseline as a muted side panel for comparison.
{
"type": "object",
"required": [
"dataset_id"
],
"properties": {
"save": {
"type": "boolean",
"default": false,
"description": "Local/stdio: also write the PNG to NIMBUS_EXPORT_DIR/plots/ and return\nits path. Ignored on the hosted gateway (the image is returned inline)."
},
"track": {
"enum": [
"within_session",
"crossSubject",
"pretrained_few_trial"
],
"type": "string",
"default": "within_session",
"description": "\"within_session\" (curated 5-fold), \"crossSubject\" (LOSO,\ncurated + BYO submissions), or \"pretrained_few_trial\" (the\nefficiency track: LOSO at the protocol's fixed per-subject\ntrial budget — the figure also includes the classical LOSO\nbaseline as a muted side panel for comparison)."
},
"dataset_id": {
"type": "string",
"description": "Dataset to chart, e.g. \"BNCI2014_001\" (see catalog.leaderboard)."
}
},
"additionalProperties": false
}{
"type": "object",
"required": [
"ok"
],
"properties": {
"ok": {
"type": "boolean"
},
"meta": {
"type": "object",
"description": "Figure sidecar. foundation.compare includes results/best/skipped (also as a JSON text content block).",
"additionalProperties": true
},
"title": {
"type": [
"string",
"null"
]
},
"mimeType": {
"type": "string"
},
"savedPath": {
"type": "string",
"description": "Set when save=true."
},
"sizeBytes": {
"type": "integer",
"description": "Set when save=true."
}
}
}{
"readOnlyHint": false,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}stream.telemetry — EEG Stream Telemetry
Live snapshot of a streaming session: latest prediction + recent window, signal quality (meanChannelQuality, snrDb, artifactProbability), indicators, running stats. Poll this while a session runs. Works with OR without a deployed model: modelless hardware streams (no classifier) report live signal quality + focus/relaxation band-power indicators with latestPrediction null; deployed sessions additionally carry predictions and confidence stats. Expect low confidence during filter/ASR warm-up (first seconds); quality < 0.5 or high artifactProbability means the signal is poor. 404 => session not active in this backend. Each poll also feeds the idle watchdog (see stream.start's idle_timeout_sec), keeping an actively watched session alive.
{
"type": "object",
"required": [
"session_id"
],
"properties": {
"window": {
"type": "integer",
"default": 50,
"description": "How many recent predictions/chunks to include (default 50)."
},
"session_id": {
"type": "string",
"description": "The streaming session to read telemetry for."
}
},
"additionalProperties": false
}{
"type": "object",
"additionalProperties": true
}{
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}data.upload — Upload Data File
Upload an EEG file (.edf/.bdf/.mat/.csv/.txt/.tsv/.h5/.hdf5, <=500MB) to the backend and get the registered path for a custom_data node. sampling_rate (Hz, e.g. 250.0) is REQUIRED for plain CSV/TSV/TXT files without embedded metadata — uploads without it are rejected (no silent 250 Hz assumption). format overrides extension-based detection (auto, mat, csv, tsv, txt, edf, bdf, h5, hdf5).
{
"type": "object",
"required": [
"file_path"
],
"properties": {
"format": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Override extension-based detection (auto|mat|csv|tsv|txt|edf|bdf|h5|hdf5)."
},
"file_path": {
"type": "string",
"description": "Local file to upload (.edf/.bdf/.mat/.csv/.txt/.tsv/.h5/.hdf5, <=500MB)."
},
"dataset_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Optional label for the uploaded dataset."
},
"sampling_rate": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"description": "Hz for headerless CSV/TSV/TXT (REQUIRED there, e.g. 250.0)."
}
},
"additionalProperties": false
}{
"type": "object",
"additionalProperties": true
}{
"readOnlyHint": false,
"openWorldHint": true,
"idempotentHint": false,
"destructiveHint": false
}data.delete_upload — Delete Upload
Delete an uploaded file from your account (disk + registry). Requires confirm=True. Pass the path returned by data.upload (file.path). Only your own uploads can be deleted; missing paths return not-found.
{
"type": "object",
"required": [
"path"
],
"properties": {
"path": {
"type": "string",
"description": "Upload path from data.upload (e.g. user_…/file.csv)."
},
"confirm": {
"type": "boolean",
"default": false,
"description": "MUST be true to delete — the explicit user go-ahead."
}
},
"additionalProperties": false
}{
"type": "object",
"additionalProperties": true
}{
"readOnlyHint": false,
"openWorldHint": true,
"idempotentHint": false,
"destructiveHint": true
}data.inspect_dataset — Inspect Dataset
Exploratory summary of a public EEG dataset (MOABB pack): channels, sampling rate, trial/class balance, per-channel µV stats, band powers and a PSD overview. Look at the data BEFORE building pipelines: class balance drives stratification choices (imbalanced classes skew accuracy), and flatlined channels mean a montage/reference problem worth fixing first. subject defaults to the dataset's catalog ``defaultSubject`` (see catalog.datasets), e.g. "S01"; a comma-list like "S01,S03" loads a cohort. mode: training | evaluation | all. Units note: values are ASSUMED volts by the loader — a µV-native file reads 1e6x too large; set unitsScale in a pipeline's custom_data config when needed.
{
"type": "object",
"required": [
"dataset"
],
"properties": {
"mode": {
"enum": [
"training",
"evaluation",
"all"
],
"type": "string",
"default": "all",
"description": "Which split to summarize — training | evaluation | all."
},
"dataset": {
"type": "string",
"description": "Dataset id from catalog.datasets (e.g. \"BNCI2014_001\")."
},
"subject": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Subject code (\"S01\") or comma-list cohort (\"S01,S03\"); defaults to\nthe catalog defaultSubject."
}
},
"additionalProperties": false
}{
"type": "object",
"additionalProperties": true
}{
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}data.inspect_file — Inspect Data File
Exploratory summary of an EEG file (.edf/.bdf/.mat/.csv/.tsv/.txt/.h5): channels, sampling rate, trial/class balance, per-channel µV stats, band powers and a PSD overview. The path shape picks the source: ABSOLUTE path → read the file from disk (only on a LOCAL backend: desktop app / MCP local mode — no upload needed); RELATIVE path (the one data.upload returns) → describe the uploaded file, which works on ANY backend (hosted or local). Look at the data BEFORE building pipelines: class balance drives stratification choices, and flatlined channels mean a montage/reference problem worth fixing first. Units note: values are ASSUMED volts by the loader — a µV-native CSV reads 1e6x too large; set unitsScale in a pipeline's custom_data config when needed. On a hosted backend absolute paths are refused with an error that explains how to proceed (upload the file first or switch to a local backend). CSV/TSV/TXT files have no embedded sampling rate: pass sampling_rate (Hz) for them — the backend never assumes 250 Hz. Formats that embed their rate (EDF/BDF/MAT/H5) ignore it.
{
"type": "object",
"required": [
"path"
],
"properties": {
"path": {
"type": "string",
"description": "ABSOLUTE filesystem path (`~` is expanded; local backends\nonly) or the RELATIVE upload path returned by data.upload\n(works on any backend)."
},
"sampling_rate": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"description": "Hz for CSV/TSV/TXT files (REQUIRED there, e.g. 250.0)."
}
},
"additionalProperties": false
}{
"type": "object",
"additionalProperties": true
}{
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}project.create — Create Project
Create a project (container for one pipeline document). Returns projectId.
{
"type": "object",
"required": [
"name"
],
"properties": {
"name": {
"type": "string",
"description": "Project display name (e.g. \"MI CSP-LDA sweep\")."
},
"description": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Optional longer description shown in the studio."
}
},
"additionalProperties": false
}{
"type": "object",
"additionalProperties": true
}{
"readOnlyHint": false,
"openWorldHint": true,
"idempotentHint": false,
"destructiveHint": false
}project.list — List Projects
List projects owned by the current principal (agent work included).
{
"type": "object",
"properties": {},
"additionalProperties": false
}{
"type": "object",
"additionalProperties": true
}{
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}project.save — Save Project Pipeline
Save a pipeline graph into a project (visible on the studio canvas). Always pass expected_revision from the last project.load (or a prior save/create response). When it does not match the current server revision, the save fails with a conflict — it does NOT silently overwrite concurrent edits. Omitting it is rejected so a stale single-writer convenience path cannot wipe another client's work.
{
"type": "object",
"required": [
"project_id",
"train_graph",
"expected_revision"
],
"properties": {
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Optional pipeline name stored on the document."
},
"subject": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Optional dataset subject code (e.g. \"S01\") for this pipeline."
},
"project_id": {
"type": "string",
"description": "Target project (from project.create/project.list)."
},
"train_graph": {
"type": "object",
"description": "Pipeline graph {nodes, connections} to persist.",
"additionalProperties": true
},
"expected_revision": {
"type": "integer",
"description": "Optimistic-concurrency base from project.load /\na prior save. Required."
}
},
"additionalProperties": false
}{
"type": "object",
"additionalProperties": true
}{
"readOnlyHint": false,
"openWorldHint": true,
"idempotentHint": false,
"destructiveHint": true
}project.load — Load Project
Load a project's saved pipeline (train graph + meta) for editing/re-running.
{
"type": "object",
"required": [
"project_id"
],
"properties": {
"project_id": {
"type": "string",
"description": "Project whose pipeline document to load."
}
},
"additionalProperties": false
}{
"type": "object",
"additionalProperties": true
}{
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}project.rename — Rename Project
Rename a project you own (max 200 characters).
{
"type": "object",
"required": [
"project_id",
"name"
],
"properties": {
"name": {
"type": "string",
"description": "New display name."
},
"project_id": {
"type": "string",
"description": "Project to rename (from project.create/project.list)."
}
},
"additionalProperties": false
}{
"type": "object",
"additionalProperties": true
}{
"readOnlyHint": false,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}project.delete — Delete Project
Delete a project (and its saved pipeline document) from the studio workspace. Requires confirm=True: this removes the project from the user's project list. Executions already run from it are not affected. Find ids with project.list.
{
"type": "object",
"required": [
"project_id"
],
"properties": {
"confirm": {
"type": "boolean",
"default": false,
"description": "MUST be true to delete — the explicit user go-ahead."
},
"project_id": {
"type": "string",
"description": "Project to delete (from project.create/project.list)."
}
},
"additionalProperties": false
}{
"type": "object",
"additionalProperties": true
}{
"readOnlyHint": false,
"openWorldHint": true,
"idempotentHint": false,
"destructiveHint": true
}protocol.validate — Validate Protocol
Validate a neurofeedback protocol document WITHOUT saving it. Returns {valid: true, spec} on success, or {valid: false, errors: [...]} with the per-violation list (loc/msg) when the document is invalid — the verdict is data, never an exception.
{
"type": "object",
"required": [
"spec"
],
"properties": {
"spec": {
"type": "object",
"description": "Wire-format protocol document (camelCase): id, name,\nindicator {name, transform}, armDefaults, blocks\n[{id, kind: assessment|training, durationSec, feedback?}],\nthreshold, sessions, breakCriteria.",
"additionalProperties": true
}
},
"additionalProperties": false
}{
"type": "object",
"additionalProperties": true
}{
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}protocol.save — Save Protocol
Validate and persist the NEXT VERSION of a protocol document (confirm-gated: each call appends a version row; accidental calls clutter the version history). Edits create a new version — the assignment pins the version it runs.
{
"type": "object",
"required": [
"spec"
],
"properties": {
"spec": {
"type": "object",
"description": "Wire-format protocol document (validate first to iterate).",
"additionalProperties": true
},
"confirm": {
"type": "boolean",
"default": false,
"description": "MUST be true to write."
},
"project_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Optional — bind the version to a project (the project\nprotocol page lists bound ids). Omitted, the id inherits its\nlatest version's binding server-side."
}
},
"additionalProperties": false
}{
"type": "object",
"additionalProperties": true
}{
"readOnlyHint": false,
"openWorldHint": true,
"idempotentHint": false,
"destructiveHint": false
}protocol.list — List Protocols
Every saved protocol id at its latest version.
{
"type": "object",
"properties": {
"project_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Optional — narrow the list to that project's\nprotocols (the project protocol page scope)."
}
},
"additionalProperties": false
}{
"type": "object",
"additionalProperties": true
}{
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}protocol.start_assignment — Start Protocol Assignment
Enroll a subject and prepare their neurofeedback deploy session (confirm-gated — a session runs on a human). Creates the assignment (yoked sham arms REQUIRE yoked_donor_upload_id: a recorded simulated session's upload — mint one by running an active-arm session and data.upload-ing its recording), then persists the protocol graph as a deployable execution. Requires a Pro plan for LIVE hardware sessions; simulated-source sessions (the default template) are free. Graph source: execution_id reuses THAT run's stored graph (it must contain a protocol_session node; no device is pre-connected — the deploy session's data source stays yours). Without execution_id the built-in template graph is cloned — simulated source → bandpass → bandpower_indicator → protocol_session stamped with the protocol refs — and a simulated device is connected to the returned session id. The session starts when a client opens {statusUrl} (the deploy WS), sends init_deployment with modelExecutionId={executionId}, then start; the Studio app shows the feedback panel automatically. Poll protocol.session_status; stop with protocol.stop (the recording's block annotations + assignment progression are written on stop).
{
"type": "object",
"required": [
"protocol_id",
"protocol_version",
"subject_label",
"arm"
],
"properties": {
"arm": {
"type": "string",
"description": "active | sham."
},
"confirm": {
"type": "boolean",
"default": false,
"description": "MUST be true — explicit go-ahead for a session on a human."
},
"protocol_id": {
"type": "string",
"description": "Saved protocol id (protocol.save)."
},
"execution_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Optional completed execution whose stored graph\ncarries a protocol_session node; default clones the template."
},
"subject_label": {
"type": "string",
"description": "Subject identifier (e.g. \"S01\")."
},
"protocol_version": {
"type": "integer",
"description": "Immutable version the assignment pins."
},
"yoked_donor_upload_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Donor recording upload (required when the\narm's blocks resolve to yoked — the backend validates coverage)."
}
},
"additionalProperties": false
}{
"type": "object",
"additionalProperties": true
}{
"readOnlyHint": false,
"openWorldHint": true,
"idempotentHint": false,
"destructiveHint": false
}protocol.session_status — Protocol Session Status
Live snapshot of a protocol deploy session: the scheduler block / session progress + threshold state (under ``protocol``) beside the telemetry window (recent indicators, quality, stats).
{
"type": "object",
"required": [
"session_id"
],
"properties": {
"window": {
"type": "integer",
"default": 50,
"description": "How many recent predictions to include (1-200, default 50)."
},
"session_id": {
"type": "string",
"description": "The deploy session to inspect (from start_assignment)."
}
},
"additionalProperties": false
}{
"type": "object",
"additionalProperties": true
}{
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}protocol.pause — Pause Protocol Session
Pause a running protocol session (blocks freeze; the session and device stay alive — resume with protocol.resume). Simulated and playback sessions only while paused: no data is recorded.
{
"type": "object",
"required": [
"session_id"
],
"properties": {
"session_id": {
"type": "string",
"description": "The deploy session to pause."
}
},
"additionalProperties": false
}{
"type": "object",
"additionalProperties": true
}{
"readOnlyHint": false,
"openWorldHint": true,
"idempotentHint": false,
"destructiveHint": false
}protocol.resume — Resume Protocol Session
Resume a paused protocol session (restarts the server-driven device loop). Live-hardware resume requires a Pro plan; simulated sessions are free. Pass the session's channel count (start_assignment reports it).
{
"type": "object",
"required": [
"session_id"
],
"properties": {
"chunk_size": {
"type": "integer",
"default": 125,
"description": "Samples per streamed chunk (default 125)."
},
"n_channels": {
"type": "integer",
"default": 4,
"description": "Session channel count (the built-in template opens 4)."
},
"session_id": {
"type": "string",
"description": "The deploy session to resume."
}
},
"additionalProperties": false
}{
"type": "object",
"additionalProperties": true
}{
"readOnlyHint": false,
"openWorldHint": true,
"idempotentHint": false,
"destructiveHint": false
}protocol.stop — Stop Protocol Session
Stop a protocol session (always safe to call): stops streaming, saves the block-annotated recording, advances the assignment when the scheduler reached its natural end, and disconnects the device (best-effort — a failed disconnect is reported, never raised).
{
"type": "object",
"required": [
"session_id"
],
"properties": {
"session_id": {
"type": "string",
"description": "The deploy session to stop."
}
},
"additionalProperties": false
}{
"type": "object",
"additionalProperties": true
}{
"readOnlyHint": false,
"openWorldHint": true,
"idempotentHint": false,
"destructiveHint": true
}protocol.export_stats — Export Protocol Stats
Paired pre/post analysis for one assignment's recorded sessions: per-block aggregates (descriptive + CSV), paired t / Wilcoxon / dz (per-statistic minimums: paired t and Cohen's dz need ≥ 3 completed sessions, Wilcoxon needs ≥ 5), specificity notes, the adaptive-threshold trajectory, and a pre/post figure (base64 PNG — render or save it to look at the effect). An assignment with no recordings yet returns the empty payload with a note, never an error.
{
"type": "object",
"required": [
"assignment_id"
],
"properties": {
"assignment_id": {
"type": "string",
"description": "The assignment to analyze (from start_assignment)."
}
},
"additionalProperties": false
}{
"type": "object",
"additionalProperties": true
}{
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}python.validate — Validate Python Model
Statically check a python_model script (BYO model class) without running it. Compiles the source and verifies the contract — a class with fit(X, y, info) and predict(X); optional predict_proba(X) unlocks confidence panels. Never executes the code, so it is safe against the hosted backend. Use it before execution.run to catch syntax errors, missing methods, or the wrong class name cheaply.
{
"type": "object",
"required": [
"code"
],
"properties": {
"code": {
"type": "string",
"description": "Python source of the model class (<=256KB UTF-8)."
},
"class_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Contract class to instantiate; omit to auto-detect the\nfirst class defining fit+predict."
}
},
"additionalProperties": false
}{
"type": "object",
"additionalProperties": true
}{
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}stats.grouped — Grouped Statistics
Cluster-aware group statistics across executions. REQUIREMENT (read first): each execution must have been run with an evaluation plan that STORED per-SUBJECT accuracies for at least 3 subjects — e.g. leave-one-subject-out (LOSO) or grouped CV over >= 3 subjects. Session groups within one subject (multi-session single-subject runs) are refused with ``nimbus.stats.non_subject_groups`` — those are not independent subjects. A plain single-subject CV run with no subject/session grouping stores no group stats and fails with ``nimbus.stats.insufficient_groups``. HOW to get grouped stats: in the train graph set ``public_data.subject`` to >= 3 subjects (e.g. "S01,S02,S03", mode "all"), add an ``evaluation_plan`` node wired right after public_data with ``method: "loso"`` and ``evaluationTargetNodeId`` = your model node id, and keep an ``epoching`` node. See catalog.node_schema("evaluation_plan") and the ``mi_bciiv2a_csp_cv`` template for a working plan. What it does: pools the per-subject accuracies each run's evaluation plan stored, then reports the between-group summary — mean accuracy with a t-interval and a one-sample t-test vs chance. Responses label ``groupKind``, real ``groupKeys`` (subject ids like S01 when stamped or recoverable), ``perGroup`` (key + accuracy pairs), ``overall.pooledExecutionIds``, and ``kindBreakdown`` / ``overall.kindBreakdown`` (per_subject vs loso etc. with n + mean — #470; between-group pooled mean is unchanged).
{
"type": "object",
"required": [
"execution_ids"
],
"properties": {
"chance": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"description": "Chance level in [0, 1]; default 1/nClasses per execution."
},
"execution_ids": {
"type": "array",
"items": {
"type": "string"
},
"description": "1–25 executions (from execution.run) to pool. Runs\nwithout subject group stats are reported with nulls but do not\nfail the request — unless NONE qualifies\n(``nimbus.stats.insufficient_groups``) or only session groups\nare present (``nimbus.stats.non_subject_groups``)."
}
},
"additionalProperties": false
}{
"type": "object",
"additionalProperties": true
}{
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}foundation.compare — Compare Foundation Backbones
Run every available pretrained backbone on YOUR data and see which wins — a ranked bar chart with CI whiskers, params, and wall time per backbone. Backbones that can't process your data (window size, channel count) are noted, not silently skipped. Each backbone embeds your trials frozen (the exact foundation_features preprocessing), a LDA is cross-validated on the embeddings. Returns a PNG image PLUS a JSON text block (and structuredContent.meta.results) with per-backbone accuracy, CI, embed dim, params, and time — pick the foundation_features backbone by measurement, not vibes.
{
"type": "object",
"required": [
"source"
],
"properties": {
"mode": {
"enum": [
"training",
"evaluation",
"all"
],
"type": "string",
"default": "all",
"description": "Pack split to load: training | evaluation | all (source=dataset)."
},
"path": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Upload path (source=upload) or absolute local path (source=local)."
},
"source": {
"enum": [
"dataset",
"upload",
"local"
],
"type": "string",
"description": "\"dataset\" (MOABB pack), \"upload\" (path from data.upload), or\n\"local\" (absolute path, local backend only)."
},
"dataset": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "MOABB dataset id, e.g. \"BNCI2014_001\" (source=dataset)."
},
"subject": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Subject id, e.g. \"S01\" (source=dataset)."
}
},
"additionalProperties": false
}{
"type": "object",
"required": [
"ok"
],
"properties": {
"ok": {
"type": "boolean"
},
"meta": {
"type": "object",
"description": "Figure sidecar. foundation.compare includes results/best/skipped (also as a JSON text content block).",
"additionalProperties": true
},
"title": {
"type": [
"string",
"null"
]
},
"mimeType": {
"type": "string"
},
"savedPath": {
"type": "string",
"description": "Set when save=true."
},
"sizeBytes": {
"type": "integer",
"description": "Set when save=true."
}
}
}{
"readOnlyHint": true,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": false
}Prompts
5 advertised
mi_csp_lda_bci_iv_2a — Train CSP+LDA on BCI IV 2a
Run the built-in motor-imagery CSP -> LDA template and show the confusion matrix.
compare_mi_pipelines — Compare MI pipelines
One paced experiment: CSP+LDA vs FBCSP+LDA vs EEGNet on BCI IV 2a.
foundation_backbones — Pick a foundation backbone
Benchmark every pretrained EEG backbone on a dataset and pick the best one.
inspect_my_eeg — Inspect my EEG file
Upload a recording and get an exploratory summary before building a pipeline.
leaderboard_standing — Check the leaderboard
See the public leaderboard and where your submissions stand.
Resources
0 advertised
90-day uptime
A lightweight connection check about every six hours, sampled on hosts with many listings. It shows the server answered, not that its tools work.
- 2026-11-07: 1 of 1 checks answered
30-day availability
Aggregated from read-only remote checks; this is not a tool-execution or security guarantee.
- Successful checks
- 1 of 1 (100%)
- Average latency
- 713 ms
- 95th percentile latency
- 713 ms
Maintenance history
Public check and source-refresh events. Editorial and ownership records remain private.
- · probe · passed · 713 ms · metadata changed · 63 tool(s), 0 resource(s), 0 resource template(s), 5 prompt(s)
Connect from your client
Each snippet registers the same endpoint; pick the client you use.
Claude Code
claude mcp add --transport http nimbus-bci-mcp-fly https://nimbus-mcp.fly.dev/mcpCodex
codex mcp add nimbus-bci-mcp-fly --url https://nimbus-mcp.fly.dev/mcpCursor
{
"mcpServers": {
"nimbus-bci-mcp-fly": {
"url": "https://nimbus-mcp.fly.dev/mcp"
}
}
}Cline
{
"mcpServers": {
"nimbus-bci-mcp-fly": {
"type": "streamableHttp",
"url": "https://nimbus-mcp.fly.dev/mcp",
"disabled": false
}
}
}VS Code
{
"servers": {
"nimbus-bci-mcp-fly": {
"type": "http",
"url": "https://nimbus-mcp.fly.dev/mcp"
}
}
}Gemini CLI
gemini mcp add --transport http nimbus-bci-mcp-fly https://nimbus-mcp.fly.dev/mcpClaude Desktop
https://nimbus-mcp.fly.dev/mcpWindsurf
{
"mcpServers": {
"nimbus-bci-mcp-fly": {
"serverUrl": "https://nimbus-mcp.fly.dev/mcp"
}
}
}Let your agent find its tools
Find servers like Nimbus BCI MCP from your agent. Add Koskamo once to search the index for endpoints, access requirements, and client setup. Public discovery needs no key.