MCP HeartbeatTHE MCP OBSERVATORY
Public workspace

Explore

Evidence for your next connection.

Independent measurements of remote MCP servers. Every observation has a timestamp.

Read-only probes

MCP server · Code & DevOps

Nimbus BCI

BCI/EEG toolkit: public MOABB/BNCI datasets, pipeline build/validate, hosted training, BIDS export.

Checks passed
14 / 22

0 failed · 8 not measured

Median response
588 ms

Median of successful probes over 7 days

30-day uptime
Not measured

Share of countable probes over 30 days, including daily rollups. Auth challenges are excluded.

Discovered tools
63

Tool definitions returned by this server

Independent monitoring

Health & checks

Status history

Responded

The server completed its last measured handshake. This is an observation, not a guarantee.

Last checked
Check summary by test group
Test areaPassedFailedUnmeasured
ConnectionCan a client connect and discover tools?
500
Reliability & speedDoes it respond consistently and quickly?
004
Access & authenticationWhat is required to use this server?
102
Tool qualityAre the tool definitions usable by an agent?
400
Publisher identityCan the publisher be traced to its source?
402

Unmeasured means there is not enough evidence to decide. How these checks work

Inspect individual checks 22 recorded

Core

  • Pass
    Reachable

    Latest probe returned HTTP 200 in 588 ms.

  • Pass
    Valid handshake

    protocolVersion 2025-11-25, serverInfo.name nimbus.

  • Pass
    Lists tools

    tools/list returned 63 tools.

  • Pass
    Current protocol

    Negotiated 2025-11-25. The bar is 2025-06-18 or newer.

  • Pass
    HTTPS

    The endpoint URL is https.

Performance

  • Not measured
    Fast (p50)

    Median latency 588 ms over 1 samples in 7 days. The bar is 1000 ms. Need at least 5 samples.

  • Not measured
    Consistent (p95)

    95th percentile 588 ms over 1 samples in 7 days. The bar is 3000 ms. Need at least 20 samples.

  • Not measured
    Reliable (uptime)

    1 of 1 attempts returned a tool list in 30 days (100%). The bar is 99%. Need at least 30 samples.

  • Not measured
    Stable tool list

    Fewer than two successful probes in 30 days, so tool-list stability is not measured.

Access

  • Pass
    Open access

    tools/list succeeded with no credential, and the record declares none.

  • Not measured
    Standard auth

    Auth is not required, so the OAuth metadata check does not apply.

  • Not measured
    Free tier cited

    No publisher quote has been checked.

Tools

  • Pass
    Tools described

    Every tool description is at least 20 characters.

  • Pass
    Valid input schemas

    Every inputSchema is a JSON Schema object.

  • Pass
    Parameters documented

    173 of 173 parameters have a description (100%). The bar is 80%.

  • Pass
    Safety hints

    Every tool sets readOnlyHint or destructiveHint.

Publisher

  • Pass
    Verified namespace

    Listed in the Official MCP Registry.

  • Not measured
    Website matches publisher

    This namespace is not a reverse domain, so the website comparison does not apply.

  • Pass
    Source repo linked

    A repository URL is on file.

  • Pass
    Repo owner matches

    The GitHub repository owner matches the namespace login.

  • Pass
    Recently updated

    Updated 2026-11-03T21:23:47.699596Z, within 180 days.

  • Not measured
    Open-source licence

    The GitHub licence lookup has not returned an OSI result yet.

Start using Nimbus BCI

Connect to this server

Choose your client, copy the configuration, then enable the server in your client’s MCP settings.

Run this command in your terminal, then restart Claude Code.

Claude Code

claude mcp add --transport http nimbus-bci https://nimbus-mcp.fly.dev/mcp

Capabilities

Tools 63

account.whoami

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.

Discovered
bids.export_dataset

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.

Discovered
bids.export_execution

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.

Discovered
calibration.pause

Pause a running calibration between trials (cues hold; resume anytime).

Discovered
calibration.resume

Resume a paused calibration session.

Discovered
calibration.start

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).

Discovered
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.

Discovered
calibration.train

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.

Discovered
catalog.datasets

Curated public EEG datasets (MOABB packs) available to pipelines.

Discovered
catalog.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.

Discovered
catalog.node_schema

Full config JSON schema + input/output ports for one node type.

Discovered
catalog.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.

Discovered
catalog.template

Full template incl. the 'train' execGraph needed by execution.run/pipeline.validate.

Discovered
catalog.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.

Discovered
data.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.

Discovered
data.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.

Discovered
data.inspect_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.

Discovered
data.upload

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).

Discovered
device.list

EEG devices supported by this backend (OpenBCI, Muse, BrainBit, LSL, PiEEG...).

Discovered
device.test

Test a device connection WITHOUT starting a stream (safe, no confirm needed).

Discovered
execution.artifacts

Trained artifacts (models/filters, e.g. *.pkl) saved by an execution.

Discovered
execution.cancel

Cancel a running execution.

Discovered
execution.delete

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.

Discovered
execution.download_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.

Discovered
execution.get

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.

Discovered
execution.list

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.

Discovered
execution.results

Metrics for a completed run. Trimmed by default (accuracy, kappa, ITR, confusion matrix, per-class); full=True returns the complete result object.

Discovered
execution.run

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.

Discovered
experiment.delete

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.

Discovered
experiment.get

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).

Discovered
experiment.run

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).

Discovered
foundation.compare

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.

Discovered
leaderboard.mine

List your leaderboard submissions (newest first), all datasets.

Discovered
leaderboard.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.

Discovered
leaderboard.submit

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.

Discovered
pipeline.export

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``.

Discovered
pipeline.validate

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().

Discovered
pipeline.validate_node

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).

Discovered
plots.confusion

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.

Discovered
plots.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.

Discovered
plots.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.

Discovered
plots.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.

Discovered
project.create

Create a project (container for one pipeline document). Returns projectId.

Discovered
project.delete

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.

Discovered
project.list

List projects owned by the current principal (agent work included).

Discovered
project.load

Load a project's saved pipeline (train graph + meta) for editing/re-running.

Discovered
project.rename

Rename a project you own (max 200 characters).

Discovered
project.save

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.

Discovered
protocol.export_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.

Discovered
protocol.list

Every saved protocol id at its latest version.

Discovered
protocol.pause

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.

Discovered
protocol.resume

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).

Discovered
protocol.save

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.

Discovered
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).

Discovered
protocol.start_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).

Discovered
protocol.stop

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).

Discovered
protocol.validate

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.

Discovered
python.validate

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.

Discovered
stats.grouped

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).

Discovered
stream.start

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.

Discovered
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).

Discovered
stream.stop

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.

Discovered
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.

Discovered

Recent measurements

Probe history

View status
Latest stored probes. Raw probe rows are kept for 14 days.
CheckedResultResponseTools
Connected588 ms63