Skip to main content

A Model Context Protocol (MCP) server for flow cytometry data analysis

Project description

cyto-mcp

A Model Context Protocol (MCP) server that brings flow cytometry analysis to any MCP-capable AI assistant — locally, privately, and for free.


Why cyto-mcp?

Flow cytometry analysis (FCS files, gating, compensation, clustering) is tedious, error-prone, and hard to script. cyto-mcp lets an AI assistant like Claude or GitHub Copilot drive the entire analysis pipeline through natural language — while keeping every byte of your data on your own machine.

Cloud LLM  ──HTTPS──►  MCP Client (Claude Desktop / VS Code / Cursor)
                               │  stdio / local HTTP
                               ▼
                        cyto-mcp server  ──►  FCS files on your disk

No data leaves your machine. The LLM only sees compact summaries, statistics, and images that the server sends back.


Features

Category Tools
File I/O List, load, validate FCS files; read FCS keywords
Preprocessing Apply compensation matrix; Logicle / asinh / biexp transform
Quality control Time-drift detection, saturated-event flagging
Subsampling Reproducible down-sampling for fast exploration
Statistics Per-channel percentile stats; cross-sample comparison
Gating Rectangle, polygon, ellipse, quadrant, threshold gates
Visualization Scatter plots, histograms, density overlays — returned as PNG + structured JSON
Reporting Markdown / HTML summary reports

Advanced clustering (FlowSOM, UMAP) is planned for v0.2.


Quickstart

Prerequisites

Install from source

git clone https://github.com/luangxiao/cyto-mcp.git
cd cyto-mcp
uv sync                       # creates .venv and installs all deps
uv run cyto-mcp --help        # verify it works

Or with pip:

pip install -e .
cyto-mcp --help

Configure your MCP client

Claude Desktop — edit claude_desktop_config.json:

{
  "mcpServers": {
    "flow": {
      "command": "uv",
      "args": ["run", "--directory", "/path/to/cyto-mcp", "cyto-mcp", "serve",
               "--data-dir", "/path/to/your/fcs/files"],
      "env": {}
    }
  }
}

VS Code — create .vscode/mcp.json in your workspace:

{
  "servers": {
    "flow": {
      "type": "stdio",
      "command": "uv",
      "args": ["run", "--directory", "${workspaceFolder}", "cyto-mcp", "serve",
               "--data-dir", "${workspaceFolder}/data"]
    }
  }
}

Try it

In your AI assistant, ask:

"List FCS files in my data directory and load the first one. Show me the panel channels and a scatter plot of FSC-A vs SSC-A."


Architecture

See ARCHITECTURE.md for a detailed description of the codebase layout, design decisions, and extension guide.

src/flow_mcp/
├── server.py          # FastMCP app wiring and startup
├── cli.py             # click CLI entry point  (`cyto-mcp serve`)
├── config.py          # Pydantic settings (data-dir, output-dir, cache size)
├── errors.py          # Typed error hierarchy
├── cache.py           # LRU in-memory sample cache
├── tools/
│   ├── io.py          # load_fcs, list_fcs, fcs_keywords, validate_fcs
│   ├── preprocess.py  # apply_compensation, transform
│   ├── qc.py          # quality_check
│   ├── stats.py       # channel_stats, compare_samples
│   ├── gating.py      # gate_*, population_stats
│   └── plots.py       # scatter_plot, histogram, density_plot
└── utils/
    ├── image.py       # fig → PNG bytes helper
    └── paths.py       # safe path resolution within data-dir sandbox

Design principles

  1. Data never leaves the machine. The server only reads files from the configured --data-dir and writes outputs to --output-dir. No network calls.
  2. Return references, not raw data. Large artefacts (PNG plots, reports) are written to disk and referenced by URI. Tool responses stay small enough to fit in any context window.
  3. Dual return for plots. Every plot tool returns both a PNG image (for the human) and a structured JSON summary (for the LLM to reason about numerically).
  4. Sandboxed file access. All path arguments are resolved relative to --data-dir and validated to prevent path traversal attacks.
  5. Stateless tools, stateful cache. Each tool call is self-contained; the LRU sample cache is an optimisation, not a requirement for correctness.

Community & Discussion

I'm a solo developer building this in my spare time — I'd genuinely love to hear from you, whether you're a researcher, clinician, bioinformatician, or just curious.

  • Questions / ideas? → open a Discussion — no question is too basic.
  • Found a bug? → open an Issue with steps to reproduce.
  • Want to share a use-case or analysis workflow? → post it in Show and Tell, I genuinely enjoy seeing real-world applications.
  • Working on something adjacent (FlowSOM, batch QC, GatingML)? Start a discussion before building — I'm happy to collaborate or at least avoid duplicated effort.

Contributing

All contributions are welcome — from typo fixes to new tools. Here's how to get started:

  1. Fork the repository and clone it locally
  2. Create a feature branch: git checkout -b feat/my-feature
  3. Install dev dependencies: uv sync --extra dev
  4. Run tests: uv run pytest
  5. Lint: uv run ruff check src tests
  6. Open a pull request with a clear description of what and why

For anything non-trivial, please open an issue or discussion first so we can align on approach before you invest time coding. I'll do my best to review PRs promptly and give constructive feedback.


License

Apache 2.0 — see LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

cyto_mcp-0.1.0.tar.gz (194.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

cyto_mcp-0.1.0-py3-none-any.whl (31.3 kB view details)

Uploaded Python 3

File details

Details for the file cyto_mcp-0.1.0.tar.gz.

File metadata

  • Download URL: cyto_mcp-0.1.0.tar.gz
  • Upload date:
  • Size: 194.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.16 {"installer":{"name":"uv","version":"0.11.16","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for cyto_mcp-0.1.0.tar.gz
Algorithm Hash digest
SHA256 fa4ce26b0af3e871398eb54ea244b0591d8b1ce8303fa08eda4ed087fb175f87
MD5 99d9e1762a855693bb5082dc913b14a1
BLAKE2b-256 5dbecc304e1386f7ca135ff3b76d788ac7cef6b1a9e670725019192163937493

See more details on using hashes here.

File details

Details for the file cyto_mcp-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: cyto_mcp-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 31.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.16 {"installer":{"name":"uv","version":"0.11.16","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for cyto_mcp-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 478db00114ee4019734fcf8b5c537c6facd5b3d16a7336b0f2aafea9d37e4a4a
MD5 cd3ea5044fcc21542de3b77eaf0734fc
BLAKE2b-256 42f8bf7404f32cbebb5694fb793b59b8398bcf480dc0299e132d5a9cac22e21c

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page