sciflow-mcp
Exports compiled analysis workflows/pipelines to Argo Workflows, enabling cluster execution where sessions run in parallel and aggregate steps wait for completion.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@sciflow-mcp build a workflow that computes a PSTH from spike times aligned to stimulus onsets"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
sciflow-mcp
An MCP server that lets scientists and their agents build reproducible, interoperable analysis workflows over stamped data: data positioned along time, cortical depth, frequency, or any other parametric axis.
It builds on three earlier pieces of work:
Collate: every array is paired with a stamp per sample, and multiple acquisition systems are aligned to one clock. Its
GeneralizedDatasuccessor generalizes time to any parametric axis.EventLogic: logical operations (AND, OR, NOT, merge, containment) on
[on, off]intervals.The generalized analysis functions from Barnes et al. 2026: peri-event collation, normalization and correlation that work whatever the data's dimensionality.
Install
pip install sciflow-mcpTo run the MCP server without installing anything, use uvx sciflow-mcp, for example in a client config: {"command": "uvx", "args": ["sciflow-mcp"], "env": {"SCIFLOW_STORE": "/path/to/store"}}.
For development, clone the repo:
git clone https://github.com/Claybarn/sciflow-mcp && cd sciflow-mcp && uv syncOpening the clone in Claude Code picks up the server from .mcp.json.
Related MCP server: workflow-mcp
Why it interoperates
There are exactly two artifact kinds. Both lie on a named parametric axis with a unit (time in s by default):
kind | contents | invariant |
| N-D |
|
| sorted |
|
Workflows are type-checked before they run. Every operation declares which kinds it takes and which it returns.
No
parametricAxisargument. The parametric axis is always axis 0, soperi_eventworks the same on a 1-D wheel trace, a channels × time LFP and a 32 × 32 × time imaging stack.Axes can't be mixed silently. Operations that combine artifacts require the same parametric axis and unit. Time intervals can't be applied to a depth profile, and spike sample numbers can't be mixed with seconds. The error names the fix:
reparametrize,rescale_stampsoralign_clock.Any axis can become the parametric one.
reparametrizeturns a time × depth CSD into a depth × time series. Every operation then works along depth, for examplerestrictto a cortical layer defined withdefine_intervals.Derived results stay stamped. Peri-event epochs are stamped by event position and get a
lagaxis. Their average is a series whose parametric axis islag, which can be windowed withlagintervals. Per-interval correlations are stamped by interval onset. Any output can feed any later step.
Why it's reproducible
Content-addressed artifacts. An artifact's id is the SHA-256 of its arrays and header, so identical bytes always get identical ids.
Same platform and image: results are bit-identical, so cache hits and ids carry over. This holds for a local Docker run and the same image on Slurm or Kubernetes.
Different hardware or OS: floating-point operations can differ in the last bits. A Butterworth filter computed on macOS and in the Linux image differs by up to ~7e-15 relative, which changes its id.
compare_artifactschecks that two results agree within a tolerance, and every run records Python, platform and package versions.
Deterministic step keys. Each step's cache key is
hash(op, op version, validated params, input ids). Re-running reuses results, and changing one parameter re-runs only that step and the steps downstream of it.Provenance records. Every run writes
runs/<run_id>.json. It holds the resolved workflow, Python/package/operation versions, and each step's params, inputs, output, cache key and timing. Each output artifact also records the step that made it.
Operations
sciflow ops (or the list_operations tool) prints the full list. The current 34:
intervals:
threshold_intervals(fixed or Collate'smidpointthreshold),define_intervals,event_windows,interval_union/intersection/difference/xor/complement,merge_intervals,filter_intervals,select_containedseries:
restrict,select,reduce_axis,reparametrize,events_where(e.g. spikes of chosen clusters),arithmetic,standardizefiltering:
butter_filter,median_filter,bin_average(downsample along any axis, with a circular mean for phase)peri-event:
peri_event,peri_event_normalize(dff / zscore / subtract),epoch_average,event_histogram(PSTH)correlation:
interval_correlation,pairwise_interval_correlationdataset:
stack_sessions,group_reduce(hierarchical: sessions → subjects → conditions)stats:
permutation_test(stratified, from Claybarn/permute),mixed_model(statsmodels MixedLM)alignment:
align_clock(Collate's pulse cross-correlation plus linear fit; converts ticks or frame numbers to the reference unit),rescale_stamps,interpolate_to
The filtering, threshold, rescaling and events_where operations cover the preprocessing that each AcquisitionSystem subclass in Collate's examples re-implemented by hand. Examples are LFP/EMG high-pass filtering, median-filtered sync lines, OpenEphys sample numbers, Kilosort cluster labels and the miniscope's low-pass dF/F baseline. Each becomes a workflow step with recorded parameters.
Workflows
name: running-onset-widefield
inputs: {wheel: sha256:…, widefield: sha256:…, sync_ref: sha256:…, sync_img: sha256:…}
steps:
- {id: aligned, op: align_clock, inputs: {target: inputs.widefield, local_clock: inputs.sync_img, reference_clock: inputs.sync_ref}}
- {id: running, op: threshold_intervals, inputs: {series: inputs.wheel}, params: {threshold: 2.0}}
- {id: epochs, op: peri_event_normalize, inputs: {series: steps.aligned, events: steps.running},
params: {pre: 2, post: 4, baseline_start: -2, baseline_stop: 0, method: dff}}
- {id: response, op: epoch_average, inputs: {epochs: steps.epochs}}See examples/running_response.yaml. To run it end to end on synthetic two-clock data:
uv run python examples/make_demo_data.pyuv run python examples/run_demo.pyDatasets: experiment → subject → session
A dataset is a manifest of sessions. Each session has a subject, attributes (condition, day, genotype, …) and named inputs, given as artifact ids or as files to import. register_dataset imports the files and stores the resolved manifest under a content-derived dataset: id, so the id pins the exact data.
A pipeline runs the same session_steps on every session. collect stacks a chosen per-session result along a new session axis, carrying each session's subject and attributes. aggregate_steps then combine the stacks:
name: running-onset-lfp-by-condition
dataset: dataset:b30a456710f97312
where: {day: [1, 2]} # optional session filter
session_steps:
- {id: running, op: threshold_intervals, inputs: {series: inputs.wheel}, params: {threshold: 2}}
- {id: epochs, op: peri_event_normalize, inputs: {series: inputs.lfp, events: steps.running},
params: {pre: 1, post: 2, baseline_start: -1, baseline_stop: 0, method: zscore}}
- {id: response, op: epoch_average, inputs: {epochs: steps.epochs}}
collect: {responses: response}
aggregate_steps:
- {id: condition_mean, op: group_reduce, inputs: {series: inputs.responses},
params: {group_by: [condition], within: [subject], statistic: mean}}Averaging is hierarchical.
group_reducewithwithin: [subject]averages each subject's sessions before combining subjects. A subject with more sessions doesn't dominate, andstatistic: semgives the standard error across subjects, not sessions.Pipelines compile to ordinary workflows. Session steps become
<session>__<step>, so validation, caching, provenance and the Slurm/Argo exporters all apply unchanged. On a cluster, sessions run in parallel and the aggregate steps wait for all of them.Adding a session only runs that session. Everything else is a cache hit, and because results are keyed by content, sessions with identical inputs even share results. A pipeline's run record includes the pipeline and dataset id.
Results export as a long-format table.
export_artifact(format="table")writes one row per element, with columns for every axis plus subject, condition and other attributes. That's ready for mixed-effects models in R or statsmodels.
Statistics that use every session
Both tests run on a stacked series and test every element (each lag × channel, each pixel) separately, without first averaging sessions within subject:
permutation_testcalls yourmultitest_stratified_permutationtest. It shuffles condition labels only within eachstrataattribute (defaultsubject), so repeated sessions are never treated as independent.correction: max(the default) is the permutation max-statistic (Westfall–Young) FWER correction. Each test's statistic is first standardized by its own null, so channels on different scales compete fairly. Holm, Bonferroni and FDR (BH) are also available.Strata missing a condition are dropped and listed in the metadata, and elements with missing data get NaN. Without this, the raw function marks every test as significant at the minimum p-value.
The seed is a parameter, so the result is cacheable and reproducible. With
strata: nullit falls back tomultitest_two_sample.
mixed_modelfitsformula(e.g.value ~ condition + C(day)) with a random intercept pergroups(orre_formulaslopes) at every element. Output addstermandstatisticaxes (estimate, se, z, p, Holm-corrected p). Failed fits and convergence warnings are counted in the metadata.
Results stay on the parametric axis (lag), so p-values can be restricted to a window, plotted or exported to a table.
Seeing a pipeline
visualize_workflow returns Mermaid text, or the node/edge graph as JSON for a visual editor such as the Genepi rete-js frontend. Pipelines are drawn with session steps collapsed into one "each of N sessions" block, and every edge is labeled with its artifact kind. examples/onset_pipeline.mmd is the rendered demo pipeline.
examples/dataset_demo.py builds a synthetic 4-subject × 2-condition × 2-day experiment and runs examples/onset_pipeline.yaml on it. The result recovers the planted 1.6× condition effect (5.05 vs 3.19). The permutation test (max-corrected) and the mixed model both find the condition effect in the first 100–150 ms after onset.
MCP tools
tool | purpose |
| discover operations and the JSON schema of their params |
| register an experiment's sessions (importing files) and inspect it |
|
|
| parametric axis and unit, shape, axes, extent, sample rate, NaN fraction, provenance |
| static check of a workflow or pipeline: references, cycles, kinds, params |
| check two results agree within a tolerance, e.g. a laptop run vs a cluster run |
| Mermaid flowchart or node/edge graph of a workflow or pipeline |
| execute a workflow or pipeline locally and read the provenance record |
| compile to Slurm ( |
|
|
This repo's .mcp.json registers the server for Claude Code, with the store in ./.sciflow. For other clients, use absolute paths:
{"command": "uv", "args": ["run", "--directory", "/path/to/sciflow-mcp", "sciflow-mcp"], "env": {"SCIFLOW_STORE": "/path/to/store"}}Running on a cluster
Both exporters run each step as sciflow run-step <workflow.json> <step> --store <store> against a shared store. Results pass between jobs through the content-addressed cache, so a cluster run and a local run produce identical artifact ids.
Slurm:
export_workflow(target="slurm")writes one.sbatchper step and asubmit.shthat chains them with--dependency=afterok. The store must be on a shared filesystem.Kubernetes:
export_workflow(target="argo")writes a ConfigMap (the workflow) plus an ArgoWorkflowDAG. The store is a ReadWriteMany PVC mounted at/store. Build the step image with the includedDockerfile. It installs exactly the versions inuv.lock.
Development
uv syncuv run pytestTo develop against a local EventLogic checkout, uncomment [tool.uv.sources] in pyproject.toml.
Fixes relative to the MATLAB generalized functions
binEventDataToEvents/collate_event_data_to_eventspassed every event's window on every loop iteration.event_histogramuses each event's own window.collatePairwiseCorrContinuousDataToEventscorrelateddata1with itself. The port correlatesdata1withdata2.The correlation helpers' exponent
0.args.post_event_seconds(a find-and-replace accident) is back to a square root.The Python translations matched each event to the first sample at or after it (
searchsorted). sciflow defaults to the nearest sample;peri_eventandperi_event_normalizetakematch: "next"to reproduce the original. The windows' 0-based bounds check (ind - pre >= 0) also fixes the off-by-one carried over from MATLAB's 1-based> 0.binEventDataToEventssummed over events.event_histogramkeeps one row per event;epoch_averagewithstatistic: sumgives the original total.
datetime64 timestamps and ISO-date CSV columns are converted to seconds since the Unix epoch, recorded as time_origin in the artifact's meta, so daily or market data works too (e.g. pre: 2592000 for 30 days).
Workarounds for EventLogic 0.2.0
Events.__xor__is broken. XOR is composed as(a | b) & ~(a & b).The sweeps assume each operand is internally non-overlapping, so inputs are normalized with
self_or()first.
Available Tools
14 toolscompare_artifactsA
Check whether two artifacts agree numerically, e.g. the same step run on a laptop and on a cluster. Ids are hashes of exact bytes, so different hardware can give different ids for results that agree to ~1e-15; this compares kind, axes, stamps, coordinates and data within |a - b| <= atol + rtol * |b|.
Inputs: a (required), b (required), atol, rtol. Returns: object
describe_operationC
Full documentation and JSON schema of an operation's parameters.
Inputs: name (required). Returns: object
export_artifactC
Write an artifact to disk as .npz, .mat (Collate struct layout, readable in MATLAB), .csv, or 'table': a long-format CSV with one row per element and columns for every axis plus subject / condition / other attributes of stacked sessions (ready for mixed-effects models in R or statsmodels).
Inputs: path (required), artifact_id (required), format. Returns: object
export_workflowB
Compile a workflow or pipeline into cluster jobs that each run one step against a shared store (a pipeline's sessions run in parallel; its aggregate steps wait for all of them).
slurm options: store_path, partition, time, mem, cpus, account, setup (shell lines, e.g. module load), sciflow_cmd, extra_sbatch. argo options: image, namespace, store_pvc, cpu, memory.
Inputs: target (required), out_dir (required), workflow (required), options. Returns: object
get_datasetC
A registered dataset's sessions, subjects, attributes and input artifact ids. With no id, lists datasets.
Inputs: dataset_id. Returns: result
get_runA
Full provenance record of a run (resolved workflow, environment and package versions, every step's params, inputs, outputs and cache key). With no run_id, lists recent runs.
Inputs: run_id. Returns: result
import_dataB
Import a .npy/.npz/.mat/.csv file into the store and return its artifact id.
Series: the array under data_key with its parametric axis at index parametric_axis, paired with
stamps_key (default 'stamps' or Collate's 'timestamps'), or stamps generated from sample_rate and
start. ticks_per_unit divides raw stamps (e.g. 30000 for sample numbers at 30 kHz). axes labels
every axis, the first naming the parametric axis; or pass just axis (e.g. "depth") and its unit.
Intervals: ons_key/offs_key, or times_key for point events, on parametric axis.
stream selects one struct in a Collate-style .mat file. CSV series use stamp_column (default: first).
Inputs: path (required), axes, axis, kind, +14 more. Returns: object
inspect_artifactA
Summarise an artifact (parametric axis and unit, shape, axes, extent, sample rate, NaN fraction) and how it was produced. Accepts a full id or a unique prefix.
Inputs: artifact_id (required). Returns: object
list_artifactsB
List every artifact in the store.
Inputs: no named parameters. Returns: result
list_operationsA
List available operations with their input kinds and output kind. Optionally filter by category (intervals, series, filtering, peri-event, correlation, alignment).
Inputs: category. Returns: result
register_datasetB
Register an experiment: {name, sessions: [{id, subject, attributes: {condition: ..., day: ...}, inputs: {: | {path, kind, options}}}]}. File inputs are imported (options are import_data's keyword arguments). Returns a content-derived dataset id that pins the exact data.
Inputs: dataset (required). Returns: object
run_workflowA
Run a workflow or pipeline locally. Steps whose (operation, version, params, inputs) already ran are
reused from cache unless force, so adding sessions to a dataset only runs the new ones. Returns run_id,
per-step outputs (summarised for pipelines) and the workflow outputs.
Inputs: workflow (required), force. Returns: object
validate_workflowA
Statically check a workflow or pipeline (JSON object, YAML/JSON text, or file path): references, cycles, input/output kinds and parameters. Returns the execution order and each step's output kind; pipelines are compiled first (session steps appear as '__').
Inputs: workflow (required). Returns: object
visualize_workflowA
Draw a workflow or pipeline: Mermaid flowchart text (render it for the user), or the node / edge graph as JSON for a visual editor. Pipelines show their session steps once, inside an 'each of N sessions' block, with the artifact kind on every edge.
Inputs: workflow (required), format. Returns: object
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 14 tools
Most tools map to a distinct resource+action: operations (list/describe), artifacts (import/list/inspect/compare/export), datasets (register/get), workflows (validate/run/visualize/export) and runs (get_run). The only soft overlaps are the four *_workflow tools and three *_artifact tools, but their descriptions (static check vs. execute vs. draw vs. compile to cluster jobs; inspect vs. compare vs. write to disk) clearly separate them. get_dataset doubling as 'list datasets' when no id is given is a minor collision with list_artifacts.
Every tool follows a single snake_case verb_noun convention (list_operations, register_dataset, run_workflow, export_artifact). Verbs are reused consistently for the same intent (list_, get_, export_, *_workflow), making the surface predictable.
14 tools sits squarely in the well-scoped range and each one corresponds to a real lifecycle stage (discovery, import/store, dataset registration, workflow validate/run/visualize/export, provenance, artifact export). No obviously redundant or filler tools.
The core pipeline is covered end to end: discover operations, import data, register datasets, validate/run/visualize/export workflows, inspect provenance, and export results for R/statsmodels. Gaps are minor: no delete/prune for artifacts or datasets, no explicit in-memory artifact data read (only summary via inspect or disk write via export), and no workflow listing tool.
Maintenance
Related MCP Connectors
Plan and verify evidence-aware research workflows with specialist execution receipts.
Deterministic research automation with live OpenAlex search and reusable workflow programs.
Shared workspace for AI artifacts: your agents publish, search and cite each other's work.
Provenance-first database for teams and agents: every value carries sources, rules and coverage.
Related MCP Servers
- AlicenseNot gradedqualityBmaintenanceEnables creation and invocation of reusable research workflow programs derived from demonstrations, with live scholarly data search and workspace automation via multiple protocols.MIT
- AlicenseNot gradedqualityCmaintenanceEnables deterministic, resumable workflow automation through DAG step graphs, boolean gate branching, automatic parallel execution, and in-step agent loops with sandboxed file and command tools.7 npm1MIT
- AlicenseNot gradedqualityBmaintenanceEnables agents to track ML experiments with a reproducible write contract, internal git snapshots, and a queryable knowledge graph, plus a live web UI for humans.Apache 2.0
- FlicenseNot gradedqualityBmaintenanceEnables deterministic, harness-neutral research workflows by unifying research object identity, evidence receipts, claim-evidence graphs, and append-only decision logs, along with specialized scholarly skills for literature analysis, reproducibility audits, and multi-agent review.206 PyPI1-