Skip to main content
Glama
MCP GeneLab Server

MCP GeneLab Server

by sbl-sdsc

MCP GeneLab Server

License: BSD-3-Clause Python 3.10+ Model Context Protocol PyPI version

A Model Context Protocol (MCP) server that converts natural language queries into Cypher queries and executes them against the configured Neo4j endpoints. Customized tools provide seamless access to the NASA GeneLab Knowledge Graph (spoke-genelab v0.3.1), enabling AI-assisted analysis of spaceflight experiments and their biological effects. This server allows researchers to query differential gene expression, DNA methylation, and differential organism abundance data from NASA's space biology experiments through natural language interactions with AI assistants like Claude.

The GeneLab Knowledge Graph integrates omics data from NASA's Open Science Data Repository (OSDR), with nodes that can be used as connectors to other knowledge graphs, such as the SPOKE (Scalable Precision Medicine Open Knowledge Engine) knowledge graph. This integration connects spaceflight experimental results with a comprehensive biological context, including genes, proteins, anatomical structures, pathways, and diseases.

This server is part of the NSF-funded Proto-OKN Project (Prototype Open Knowledge Network). It's an extension of the Neo4j Cypher MCP server.

Table of Contents

Related MCP server: SPARQL MCP Server

Building and Querying the SPOKE-GeneLab Knowledge Graph

Presentation

Knowledge Graph Schema (v0.3.1)

The SPOKE-GeneLab KG v0.3.1 contains the following node and relationship types:

The MCP-GeneLab server uses the SPOKE-GeneLab v0.3.1+20260311 release. Any new datasets or processed data added to OSDR after March 11, 2026 is not available through the MCP-GeneLab server.

Nodes: Study, Mission, Assay, MGene, Gene, MethylationRegion, Organism, Anatomy, CellType

Relationships:

  • (Mission)-[:CONDUCTED_MIcS]->(Study) — Mission conducted a study

  • (Study)-[:PERFORMED_SpAS]->(Assay) — Study performed an assay

  • (Assay)-[:MEASURED_DIFFERENTIAL_EXPRESSION_ASmMG]->(MGene) — Differential gene expression

  • (Assay)-[:MEASURED_DIFFERENTIAL_METHYLATION_ASmMR]->(MethylationRegion) — Differential methylation

  • (Assay)-[:MEASURED_DIFFERENTIAL_ABUNDANCE_ASmO]->(Organism) — Differential organism abundance

  • (Assay)-[:INVESTIGATED_ASiA]->(Anatomy) — Assay investigated an anatomical structure

  • (Assay)-[:INVESTIGATED_ASiCT]->(CellType) — Assay investigated a cell type

  • (MGene)-[:IS_ORTHOLOG_MGiG]->(Gene) — Model organism gene is ortholog of human gene

  • (MGene)-[:METHYLATED_IN_MGmMR]->(MethylationRegion) — Gene is methylated in a region

Features

Querying & Analysis

  • Natural Language Querying: Ask questions in plain English — no need to write complex graph queries

  • NASA GeneLab Queries: Ask questions about spaceflight experiments in the NASA GeneLab knowledge graph

  • Differential Gene Expression Analysis: Find genes that are upregulated or downregulated in spaceflight conditions compared to ground controls

  • DNA Methylation Data: Access epigenetic changes observed in spaceflight experiments, including promoter / exon / intron / distance-to-feature filtering

  • Differential Organism Abundance: Query amplicon/metagenomics data showing changes in microbial community composition during spaceflight (DESeq2 and ANCOM-BC method-aware significance filtering)

  • Cross-Assay Intersection Analyses: Find features differentially detected across multiple assays — common DEGs, common DMRs, common DA organisms — each direction (up/down, hyper/hypo, increased/decreased) kept separate so the LLM can reason about them independently

  • Expression-Methylation Coupling: Identify differentially expressed genes whose promoter (or other gene region) is also differentially methylated in matched assays; supports pooled DM evidence across multiple methylation assays

  • Multi-Organism Support: Query data across multiple model organisms including mice, rats, and other species used in space research

  • Anatomy & Cell Type Filtering: Filter results by specific anatomical structures (UBERON ontology) or cell types (Cell Ontology) used in experiments

  • Assay Selection: Browse and filter assays by study, organism, technology, or measurement type

  • Biomedical Context Integration: Connect spaceflight gene expression changes to pathways, diseases, and other biological knowledge from SPOKE

  • Federated Queries: Combine data from GeneLab with other Neo4j knowledge graphs for comprehensive biomedical analysis

Visualization

  • Volcano Plots: Generate volcano plots showing differentially expressed genes / methylated regions / abundant organisms with significance thresholds

  • Venn Diagrams: Create Venn diagrams comparing differentially expressed genes (or DMRs, or DA organisms) across 2 or 3 assays, including an expression_methylation 2×2 grid variant for paired transcriptomic-epigenomic comparisons

  • Plot Resource Layer: Every generated plot is exposed as an MCP resource under plot://<session_id>/<filename> and via a fetch_plot tool, so clients can retrieve PNG bytes through a separate request from the tool call that produced them. A failed fetch can be retried without re-running the analysis

  • Schema Visualization: Generate visual representations of the knowledge graph schema

  • Mermaid Class Diagrams: Create and clean Mermaid-format class diagrams of the KG schema

Infrastructure

  • Read-Only Enforcement: All Neo4j sessions use READ_ACCESS mode — write operations are rejected at the Bolt protocol level, protecting the knowledge graph from modification

  • Multiple Transport Modes: Supports STDIO (local), SSE, and Streamable HTTP (remote deployment)

  • Remote Deployment: Deploy as a web service behind a TLS reverse proxy (target: CloudFront + WAF → ALB → ECS Fargate), accessible via HTTPS URL from any MCP client. Ships GET /healthz / GET /readyz routes for load-balancer health checks and built-in usage metrics (JSON usage log, CloudWatch EMF, optional /metrics) — see docs/deployment.md

  • Session Scoping: The hosted server is one shared process serving many users, so per-user state (output directory, plot registry) is keyed on a session_id obtained from create_session and passed on every tool call — nothing a user does is visible to another session

  • Docker Support: Build and deploy as a Docker container for consistent, reproducible environments

  • Multiple Access Methods: Use through Claude Desktop / claude.ai, ChatGPT, VS Code with GitHub Copilot, Gemini, or any MCP-compatible client

  • Pre-configured Setup: Ready-to-use mcp-genelab configuration files for a local STDIO connection to the spoke-genelab-v0.3.1 KG, or connect to the public endpoint at https://visualization.osdr.nasa.gov/kg/mcp with no local install

Prerequisites

Before using mcp-genelab, ensure you have:

  • Client Application: One of the following:

    • Claude Desktop or claude.ai — connect via Settings → Connectors → Add Custom Connector

    • ChatGPT (web, Developer mode) — connect via Add custom MCP server

    • VS Code with GitHub Copilot — connect via MCP server settings

    • Gemini app (personal Google Account) or Gemini CLI — connect via Connected Apps or gemini mcp add

    • Any MCP client that supports the STDIO or Streamable HTTP transport

  • Connection to the spoke-genelab-v0.3.1 knowledge graph via one of the two paths below:

    • Remote public endpoint: Connect to the hosted mcp-genelab server at https://visualization.osdr.nasa.gov/kg/mcp over HTTPS — no local install required. See Option A.

    • Local install with STDIO: Run mcp-genelab on your own machine against a local Neo4j instance holding the spoke-genelab-v0.3.1 KG. See Option B.

For the local STDIO setup you also need:

  • Operating System: macOS, Linux, or Windows

  • Python 3.10+ and the uv package manager

  • Neo4j Desktop with the spoke-genelab-v0.3.1 KG imported (installation links are provided in Option B)

Quick Start

mcp-genelab can be reached two ways: by connecting to the remote public endpoint (https://visualization.osdr.nasa.gov/kg/mcp) or by running mcp-genelab locally with STDIO. Both serve the spoke-genelab-v0.3.1 knowledge graph.

Option A: Connect to the Remote mcp-genelab Server

The public mcp-genelab endpoint is:

https://visualization.osdr.nasa.gov/kg/mcp

It is a Streamable HTTP MCP server hosted by NASA OSDR with no authentication required, so you can connect without installing anything locally. Pick your client below. (If you would rather run against your own Neo4j instance, use Option B.)

Claude (Desktop or claude.ai)

  1. Open Claude Desktop (or claude.ai)

  2. Go to Settings → Connectors (or Manage Connectors)

  3. Click Add Custom Connector

  4. Enter:

    • Name: mcp-genelab

    • MCP Server URL: https://visualization.osdr.nasa.gov/kg/mcp

  5. Click Save

  6. In the chat prompt, click the + button and toggle the mcp-genelab connector on

Documentation: Getting started with custom connectors using remote MCP

ChatGPT

  1. In ChatGPT on the web, open Settings → Apps → Advanced settings and enable Developer mode (Pro; on Business/Enterprise/Edu an admin must enable it)

  2. Go to chatgpt.com/plugins, click +, then Add custom MCP server

  3. Enter:

    • Name: mcp-genelab

    • Server URL: https://visualization.osdr.nasa.gov/kg/mcp

    • Authentication: No authentication

  4. Accept the risk notice (I understand and want to continue), then click Create as a plugin and install it

  5. In the chat prompt, type @ and select mcp-genelab

Documentation: Add custom MCP server · Developer mode and MCP apps in ChatGPT

VS Code with GitHub Copilot

  1. Open the Command Palette (Cmd+Shift+P) and run MCP: Add Server

  2. Choose HTTP, enter https://visualization.osdr.nasa.gov/kg/mcp as the URL and mcp-genelab as the server ID, and pick where to save it (workspace or global)

  3. When prompted, confirm that you trust the server so it starts

Equivalently, add this to .vscode/mcp.json (or your user MCP configuration):

{
  "servers": {
    "mcp-genelab": {
      "type": "http",
      "url": "https://visualization.osdr.nasa.gov/kg/mcp"
    }
  }
}

In Copilot Chat, open the Configure Tools button in the chat input to confirm the mcp-genelab tools are enabled.

Documentation: Use MCP servers in VS Code

Gemini

Gemini app (web; personal Google Account):

  1. Go to gemini.google.com, click Settings → Connected Apps (if you don't see it, click Personal Intelligence first)

  2. Under Custom apps, click Add a custom app and enter https://visualization.osdr.nasa.gov/kg/mcp

  3. Click Next and follow the on-screen instructions

  4. In the chat prompt, type @ and select the custom app

Documentation: Connect & manage custom apps for Gemini Apps

Gemini CLI (any Google account):

gemini mcp add --transport http mcp-genelab https://visualization.osdr.nasa.gov/kg/mcp

or add to ~/.gemini/settings.json: {"mcpServers": {"mcp-genelab": {"httpUrl": "https://visualization.osdr.nasa.gov/kg/mcp"}}}, then run /mcp inside Gemini CLI to confirm it is connected.

Documentation: Gemini CLI — MCP servers

Then ask a question like: "What organisms are represented in the spoke-genelab-v0.3.1 knowledge graph?"

Option B: Run mcp-genelab Locally with STDIO

Running mcp-genelab locally has two parts: (1) stand up a local Neo4j instance holding the spoke-genelab-v0.3.1 KG, and (2) point mcp-genelab at it via STDIO.

Step 1 — Install Neo4j Desktop and import the spoke-genelab-v0.3.1 KG

  1. Install Neo4j Desktop and create a spoke-genelab instance (with the APOC plugin) by following the Neo4j Desktop installation instructions.

  2. Import the spoke-genelab-v0.3.1 KG into that instance by following the database import instructions. Name the database exactly spoke-genelab-v0.3.1 and start the instance once the import completes.

Note the Bolt URI (default bolt://localhost:7687), username, and password of your running instance — you will need them in Step 2.

Step 2 — Install uv and configure mcp-genelab

Install uv if you don't already have it:

# macOS/Linux
curl -LsSf https://astral.sh/uv/install.sh | sh
# Windows
powershell -c "irm https://astral.sh/uv/install.ps1 | iex"

Then configure your MCP client to launch mcp-genelab over STDIO. For Claude Desktop, go to Claude → Settings → Developer → Edit Config and add the following mcp-genelab entry:

{
  "mcpServers": {
    "spoke-genelab-local": {
      "command": "uvx",
      "args": ["mcp-genelab"],
      "env": {
        "NEO4J_URI": "bolt://localhost:7687",
        "NEO4J_USERNAME": "neo4j",
        "NEO4J_PASSWORD": "neo4jdemo",
        "NEO4J_DATABASE": "spoke-genelab-v0.3.1",
        "INSTRUCTIONS": "Query the spoke-genelab-v0.3.1 KG to identify NASA spaceflight experiments containing omics datasets, specifically differential gene expression (transcriptomics), DNA methylation (epigenomics), and Amplicon (metagenomics) data."
      }
    }
  }
}

For VS Code with GitHub Copilot, add the same mcp-genelab entry to your .vscode/mcp.json (note the top-level key is servers, not mcpServers):

{
  "servers": {
    "spoke-genelab-local": {
      "command": "uvx",
      "args": ["mcp-genelab"],
      "env": {
        "NEO4J_URI": "bolt://localhost:7687",
        "NEO4J_USERNAME": "neo4j",
        "NEO4J_PASSWORD": "neo4jdemo",
        "NEO4J_DATABASE": "spoke-genelab-v0.3.1",
        "INSTRUCTIONS": "Query the spoke-genelab-v0.3.1 KG to identify NASA spaceflight experiments containing omics datasets, specifically differential gene expression (transcriptomics), DNA methylation (epigenomics), and Amplicon (metagenomics) data."
      }
    }
  }
}

Note: Set NEO4J_USERNAME, NEO4J_PASSWORD, and NEO4J_URI to match the Neo4j instance you started in Step 1. The uvx command automatically downloads and runs the latest published mcp-genelab from PyPI. Keep NEO4J_DATABASE set to spoke-genelab-v0.3.1 to match the database name you imported.

Docker Deployment

Build the MCP Server Image

cd mcp-genelab
docker build -t mcp-genelab:latest .

Run with Streamable HTTP Transport

docker run \
  --name mcp-server \
  --publish=127.0.0.1:8000:8000 \
  --env NEO4J_URI=bolt://host.docker.internal:7687 \
  --env NEO4J_USERNAME=neo4j \
  --env NEO4J_PASSWORD=yourpassword \
  --env NEO4J_DATABASE=spoke-genelab-v0.3.1 \
  --env MCP_TRANSPORT=streamable-http \
  --env MCP_HOST=0.0.0.0 \
  --env MCP_PORT=8000 \
  --detach \
  mcp-genelab:latest

The MCP server is then accessible at http://localhost:8000/mcp/, with GET http://localhost:8000/healthz (liveness) and GET http://localhost:8000/readyz (readiness — pings Neo4j) for load balancers (all under MCP_PATH_PREFIX if one is set, e.g. /kg/mcp). In any remote transport the server defaults to MCP_SESSION_POLICY=strict: clients must call create_session first and pass the returned session_id on every tool call (see docs/api.md).

Environment Variables

Variable

Default

Description

NEO4J_URI

bolt://localhost:7687 (stdio only)

Neo4j Bolt connection URI — required in remote transports (no default; the server refuses to start without it)

NEO4J_USERNAME

neo4j (stdio only)

Neo4j username — required in remote transports

NEO4J_PASSWORD

neo4jdemo (stdio only)

Neo4j password — required in remote transports; inject from a secret store

NEO4J_DATABASE

spoke-genelab-v0.3.1

Neo4j database name for the spoke-genelab-v0.3.1 KG

MCP_TRANSPORT

stdio

Transport mode: stdio, sse, streamable-http, or http

MCP_HOST

127.0.0.1

HTTP listener host (use 0.0.0.0 for Docker)

MCP_PORT

8000

HTTP listener port

MCP_PATH_PREFIX

(empty)

Public path prefix when a load balancer publishes the service under one, e.g. /kg → POST /kg/mcp, GET /kg/healthz, /kg/readyz, /kg/metrics

MCP_SESSION_POLICY

strict (remote) / implicit (stdio)

strict: every tool except create_session requires a valid session_id; lenient: only state-bearing tools do; implicit: fixed local session

MCP_SESSION_IDLE_TTL_SECONDS / MCP_SESSION_MAX_AGE_SECONDS

3600 / 28800

Session idle and absolute lifetimes

MCP_MAX_SESSIONS / MCP_MAX_PLOTS_PER_SESSION / MCP_MAX_TOTAL_PLOT_BYTES

10000 / 8 / 268435456

Session-store bounds

MCP_SESSION_EVICTION_MIN_IDLE_SECONDS

300

Minimum idle time before a session may be recycled to make room at the MCP_MAX_SESSIONS cap

MCP_MAX_REQUEST_BODY_BYTES

1048576

Maximum size of one POST /mcp body (1 MiB)

MCP_READYZ_TIMEOUT_SECONDS / MCP_READYZ_CACHE_SECONDS

4 / 2

Budget for the /readyz Neo4j ping; how long the last verdict is reused

MCP_QUERY_TIMEOUT_SECONDS / MCP_MAX_QUERY_ROWS

60 / 1000

Per-query timeout; row cap for the query tool

MCP_NEO4J_POOL_SIZE / MCP_NEO4J_ACQUISITION_TIMEOUT

20 / 30

Bolt pool per process; fail-fast on saturation

MCP_USAGE_LOG / MCP_METRICS_EMF / MCP_METRICS_ENDPOINT

1 / 0 / 0

Usage metrics: JSON usage log, CloudWatch EMF, GET /metrics

MCP_USAGE_FP_SALT

random per process

Salt for the client_fp usage-log field; set it (from a secret store) so fingerprints are comparable across restarts

MCP_METRICS_NAMESPACE / MCP_SERVICE_NAME

mcp-genelab / mcp-genelab

CloudWatch namespace for EMF metrics; service field on usage events

MCP_LOG_LEVEL

INFO

Application log level

INSTRUCTIONS

(see source)

System instructions for the LLM

Example Queries

Each link below points to a chat transcript that demonstrates how to use the mcp-genelab server to query and analyze GeneLab data hosted in the spoke-genelab-v0.3.1 Neo4j Knowledge Graph. To create a transcript of your own chat, use the prompt Create a chat transcript; the transcript can then be downloaded in .md or .pdf format.

Knowledge Graph Overview & Class Diagram

Overview of spoke-genelab v0.3.1

Node and Relationship Metadata Examples

List spoke-genelab-v0.3.1 assay node, properties, and relationships

Differential Expression Analysis with MCP tools

OSD-244 DE analysis

Differential Expression and Differential Methylation Analysis with MCP tools

OSD-48 DE and DM analysis

Differential Abundance Analysis with MCP tools

OSD-267 DA analysis

Cross-Graph Differential Expression and Associated Disease Analysis with MCP tools

OSD-161 DE and spoke-okn disease analysis

Note: To perform this example query, you will need to add the NSF OKN MCP server to your MCP client by following the instructions at https://okn.us/mcp.

Demos

Recorded demo sessions and transcripts


MCP Tools Reference

The server exposes 24 tools (22 analysis/utility tools plus create_session / end_session) and a plot://{session_id}/{filename} resource template. On the hosted endpoint every tool except create_session takes a session_id argument (see docs/api.md). Tools are listed below grouped by category. The specialist tools should be preferred over the generic query tool — server.py's DEFAULT_INSTRUCTIONS carries a TOOL SELECTION POLICY that routes natural-language requests to the right specialist.

Schema & metadata

Tool

Description

get_neo4j_schema

List all node types, their attributes, and relationships in the knowledge graph

get_node_metadata

Get descriptions of all node types from MetaNode entries

get_relationship_metadata

Get descriptions of all relationship types and their properties

visualize_schema

Generate a visual schema diagram of the knowledge graph

Study / assay browsing

Tool

Description

get_study_info

Get detailed information about a specific study and its assays (metadata + assay inventory)

select_assays

Browse and filter assays by study, organism, technology, or measurement; resolve a factor pair to one or more assay IDs

Single-assay analyses

Tool

Description

find_differentially_expressed_genes

Find up/downregulated genes for a given assay (DESeq2)

find_differentially_methylated_regions

Find hyper/hypomethylated regions for a given assay, with optional in_promoter / in_exon / in_intron / distance filters

find_differentially_abundant_organisms

Find organisms with differential abundance for a given assay (DESeq2 and/or ANCOM-BC)

Cross-assay analyses

Tool

Description

find_common_differentially_expressed_genes

Intersect DEGs across multiple assays (up and down directions kept separate)

find_common_differentially_methylated_regions

Intersect DMRs across multiple assays, with optional MethylationRegion filters

find_common_differentially_abundant_organisms

Intersect differentially abundant organisms across multiple assays

find_common_de_genes_overlapping_dm_regions

Identify DE genes whose promoter (or other region) is also differentially methylated — supports method-aware significance filtering and pooled-DM evidence across multiple methylation assays

Cypher fallback

Tool

Description

query

Execute a read-only Cypher query on the Neo4j database. Fallback for questions the specialists don't cover — the DEFAULT_INSTRUCTIONS policy directs the LLM to use specialist tools first

Plot generation, delivery, and saving

Tool / resource

Description

create_volcano_plot

Generate a volcano plot of differential expression / methylation / abundance results; PNG returned inline and registered for resource fetch

create_venn_diagram

Create a Venn diagram comparing DEGs / DMRs / DA organisms across 2 or 3 assays (also supports the expression_methylation 2×2 grid variant); PNG returned inline and registered for resource fetch

fetch_plot

Re-fetch the canonical PNG bytes of a plot previously generated in the same session from the in-memory registry (last 8 plots per session, FIFO eviction). Returns the bytes as an EmbeddedResource so clients can render them inline. Safe to call repeatedly — no Cypher, no matplotlib, no re-render

get_save_script

Return a markdown block with multiple save options for a previously generated plot: right-click save, ask-LLM-client-to-save, or fetch via the plot:// resource URI

plot://{session_id}/{filename} (resource)

MCP resource template — clients fetch PNG bytes via resources/read on plot://<session_id>/<suggested_filename>. Session-scoped so one user's plot is never addressable from another session; decoupled from the tool response that generated the plot, so a failed fetch can be retried without re-running the analysis

Sessions and output paths

Tool

Description

create_session

Start a session and obtain the session_id that every other tool requires on the hosted endpoint (call first; call again if a tool reports the session unknown/expired)

end_session

End a session immediately, discarding its output directory and plots

set_output_directory

Set the user-facing directory where plots and CSV files should be saved (per session)

get_output_directory

Return the currently configured output directory (per session)

Mermaid & transcript utilities

Tool

Description

clean_mermaid_diagram

Clean and validate a Mermaid class diagram of the KG schema

create_chat_transcript

Export the current chat as a formatted transcript

Security

All Neo4j sessions are opened with default_access_mode=READ_ACCESS, which is enforced at the Bolt protocol level by Neo4j. Any write operation is rejected with the error: "Write operations are not allowed for READ transactions." This works on both Community and Enterprise Edition.

As a second layer of defense, the query tool includes a regex-based write filter (_is_write_query()) that catches the Cypher write keywords MERGE, CREATE, SET, DELETE, REMOVE, ADD, and DROP (case-insensitive) before the query is sent to Neo4j. All queries also use session.execute_read() for transaction-level read enforcement. The two layers — server-side regex + Bolt-level READ_ACCESS — protect the knowledge graph from modification even if one layer is bypassed.

The query tool additionally rejects read-only-but-dangerous procedures that READ_ACCESS does not block (_is_forbidden_query()): LOAD CSV, apoc.load.*, apoc.export.*, apoc.trigger/periodic/refactor/create/merge/cypher/systemdb.*, dbms.*, and db.create* / db.drop* / full-text index creation. apoc.meta.* and apoc.help remain allowed for the schema tools. Every query runs with a server-side timeout (MCP_QUERY_TIMEOUT_SECONDS, 60 s) and the query tool caps results at MCP_MAX_QUERY_ROWS (1,000) rows; error messages never echo the submitted Cypher or raw driver exceptions. On the hosted endpoint, Neo4j credentials are injected at runtime (the image contains none, and remote transports refuse to start without them), per-user state is isolated by session (see MCP_SESSION_POLICY), and the usage log records only salted digests — never raw session ids or IP addresses. See docs/deployment.md for the full hardening checklist.


Development

Instructions for local development

Release history: CHANGELOG.md

Testing

The project ships a pytest suite (201 tests across 11 test files) that runs offline — no Neo4j connection, no network, no MCP transport. It guards against regressions in tool registration, annotation completeness, routing-policy language in tool docstrings, Cypher invariants (read-only enforcement, conditional LIMIT, lnfc null-safety, MethylationRegion filter propagation, pooled IN $assay_ids clause for cross-assay queries), the plot resource layer (plot:// URI registration, fetch_plot round-trips, save-instruction size guarantees), per-session isolation (two sessions can never see each other's output directory or plots; missing/unknown/expired session errors; TTL and memory bounds), the /healthz / /readyz load-balancer routes, and the usage-metrics pipeline.

pip install -r mcp-genelab-tests/requirements-test.txt
pytest

The suite runs in roughly 10 seconds and is safe to run on every commit. A GitHub Actions workflow at mcp-genelab-tests/.github/workflows/test.yml runs the suite on Python 3.10 through 3.13 for every push and pull request. See mcp-genelab-tests/tests/README.md for the per-file breakdown and instructions on adding tests for new tools.

Building and Publishing (maintainers only)

Instructions for building, testing, and publishing the mcp-genelab package on PyPI

API Reference

mcp-genelab server API

Troubleshooting

Common Issues

MCP server not appearing in Claude Desktop:

  • Ensure you've completely quit and restarted Claude Desktop (not just closed the window)

  • Check that your JSON configuration is valid (attach your config file to a chat and ask it to fix any errors)

  • Verify that uvx is installed and accessible in your PATH

Connection errors:

  • Verify the Neo4j endpoint URL is correct and accessible

  • For a local Neo4j Desktop instance, ensure the spoke-genelab instance is started and the spoke-genelab-v0.3.1 database has finished loading

  • Check that NEO4J_DATABASE is set to spoke-genelab-v0.3.1 and matches the database name you imported

Query rejected ("This query was rejected. Only read-only graph queries are permitted…"):

  • This is expected behavior. The query tool refuses write operations (CREATE, MERGE, SET, DELETE, REMOVE, ADD, DROP) and procedures that perform network I/O, bulk export, or database administration (LOAD CSV, apoc.load.*, apoc.export.*, dbms.*, …) before they reach Neo4j; anything that slips past is still blocked at the Bolt protocol level because every session uses READ_ACCESS mode.

"Error (missing session)" / "Error (unknown session)" / "Error (expired session)":

  • On the hosted endpoint every tool except create_session requires a valid session_id. Ask the assistant to call create_session and retry; sessions expire after 60 minutes idle or 8 hours total, and are lost when the server restarts.

Performance issues:

  • Complex Cypher queries may take time to execute

  • Consider breaking down complex queries into smaller parts

  • Check the endpoint's documentation for query best practices

License

This project is licensed under the BSD 3-Clause License. See the LICENSE file for details.

Citation

If you use MCP GeneLab in your research, please cite the following works:

@software{rose2026mcp-genelab,
  title={MCP GeneLab Server},
  author={Rose, P.W. and Saravia-Butler, A.M. and Nelson, C.A. and Shi, Y. and Baranzini, S.E.},
  year={2026},
  url={https://github.com/sbl-sdsc/mcp-genelab}
}

@software{rose2026spoke-genelab,
  title={NASA SPOKE-GeneLab Knowledge Graph},
  author={Rose, P.W. and Nelson, C.A. and Saravia-Butler, A.M. and Gebre, S.G. and Soman, K. and Grigorev, K.A. and Sanders, L.M. and Costes, S.V. and Baranzini, S.E.},
  year={2026},
  url={https://github.com/BaranziniLab/spoke_genelab}
}
  • Nelson, C.A., Rose, P.W., Soman, K., Sanders, L.M., Gebre, S.G., Costes, S.V., Baranzini, S.E. (2025). "Nasa Genelab-Knowledge Graph Fabric Enables Deep Biomedical Analysis of Multi-Omics Datasets." NASA Technical Reports, 20250000723. Link

  • Sanders, L., Costes, S., Soman, K., Rose, P., Nelson, C., Sawyer, A., Gebre, S., Baranzini, S. (2024). "Biomedical Knowledge Graph Capability for Space Biology Knowledge Gain." 45th COSPAR Scientific Assembly, July 13-21, 2024. Link

Acknowledgments

Funding

This work is supported in part by:

  • National Science Foundation Award #2333819: "Proto-OKN Theme 1: Connecting Biomedical information on Earth and in Space via the SPOKE knowledge graph"


For questions, issues, or contributions, please visit our GitHub repository.

Available Tools

24 tools
clean_mermaid_diagramA
Read-onlyIdempotent

Clean a Mermaid class diagram by removing unwanted elements.

    This tool removes:
    - All note statements that would render as unreadable yellow boxes
    - Empty curly braces from class definitions (handles both single-line and multi-line)
    - Strings after newline characters (e.g., truncates "ClassName

extra" to "ClassName")

    Args:
        mermaid_content: The raw Mermaid class diagram content
        
    Returns:
        Cleaned Mermaid content with note statements, empty braces, and post-newline strings removed
    

Inputs: mermaid_content (required), session_id.

create_chat_transcriptC
Read-onlyIdempotent

Prompt for creating a chat transcript in markdown format with user prompts and Claude responses.

Inputs: session_id.

create_sessionA

Start a session and obtain the session_id that EVERY other tool on this server requires.

WHEN TO USE THIS TOOL: Call this ONCE at the beginning of a conversation, before any other mcp-genelab tool. Also call it again whenever a tool replies that the session is unknown or expired.

WHY: This server runs as a single shared process serving many users at once. The session id is the only thing that keeps YOUR output directory and YOUR generated plots (retrievable via fetch_plot, get_save_script and the plot://{session_id}/{filename} resource) separate from everyone else's. It is an opaque bearer token — treat it as private to this conversation and never guess one.

LIFETIME: A session expires after a period of inactivity (default 60 min) or an absolute maximum age (default 8 h), whichever comes first. Expired sessions drop their plots; regenerate them under a new session.

RETURNS: A short message containing session_id: <token>. Extract the token and pass it as the session_id argument on every subsequent call.

Inputs: no named parameters.

create_venn_diagramA

Create Venn diagrams comparing differential data between 2 or 3 assays.

Supports multiple data types:

  • 'expression': Compares differentially expressed genes (upregulated/downregulated by log2fc)

  • 'methylation': Compares differentially methylated genes (hypermethylated/hypomethylated by methylation_diff)

  • 'abundance': Compares differentially abundant organisms (increased/decreased by log2fc; works for both DESeq2 and ANCOM-BC)

  • 'expression_methylation': Cross-comparison showing directional overlaps between differentially expressed genes from one assay and differentially methylated genes from another assay (2-way only)

Creates side-by-side Venn diagrams showing:

  • Left: Positive direction (upregulated / hypermethylated / increased abundance)

  • Right: Negative direction (downregulated / hypomethylated / decreased abundance)

For 'expression_methylation' mode, this tool computes FOUR directional overlaps so the user can see which kind of expression–methylation coupling is happening. By default (direction_pair='all') it renders all four as a 2x2 grid:

  • Hypermethylated + Downregulated (classical epigenetic silencing — promoter methylation reducing expression)

  • Hypomethylated + Upregulated (loss of methylation enabling expression)

  • Hypermethylated + Upregulated (less canonical; e.g. gene-body methylation activating expression)

  • Hypomethylated + Downregulated (less canonical; non-classical) If the user names a specific pairing (e.g. "create a Venn of hypermethylated and downregulated genes"), pass direction_pair='hyper_down' to render just that one. The summary always reports the size of all four overlaps, regardless of which subset is rendered.

Methylation region location filters (for data_type='methylation' and the methylation side of 'expression_methylation'):

  • in_promoter, in_exon, in_intron: each accepts True (include only regions where this flag is true), False (exclude regions where this flag is true), or None (no filter). Multiple filters combine with AND. For example, in_promoter=True alone restricts to promoter-overlapping regions; in_promoter=True with in_intron=False restricts to promoter regions that are NOT intronic.

  • dist_to_feature_max: when set, include only regions whose distance to the nearest gene feature is <= this value (in bp). Useful for narrowing to regions tightly associated with gene bodies. dist_to_feature on the MethylationRegion node is the bp distance from the region to the nearest annotated feature. These filters apply during the Cypher query — they reduce the set of methylation regions BEFORE the overlap computation, so each gene set is the genes that have at least one methylation region passing all the filters and the magnitude/significance criteria.

Significance filtering:

  • 'expression' and 'expression_methylation' (expression side): adj_p_value <= adj_p_threshold (default 0.05).

  • 'methylation' and 'expression_methylation' (methylation side): q_value <= q_value_threshold (default 0.05).

  • 'abundance' is method-aware: DESeq2 rows are filtered by adj_p_threshold, ANCOM-BC rows by q_value_threshold.

Magnitude filtering for 'abundance':

  • log2fc_threshold applies to every row (log2fc is populated for both methods).

  • lnfc_threshold (optional) adds an ANCOM-BC-specific |lnfc| filter; DESeq2 rows (lnfc IS NULL) pass through.

Returns a link to the plot and summary statistics.

Inputs: assay_id_1 (required), assay_id_2 (required), in_exon, data_type, +13 more.

create_volcano_plotA

Create a volcano plot for differential data from the given assay.

Works for three differential measurement types:

  • 'expression': -[MEASURED_DIFFERENTIAL_EXPRESSION_ASmMG]-> MGene x = log2fc, y = -log10(adj_p_value), labels = gene symbol Magnitude filter: log2fc_threshold (default 1.0 = 2-fold)

  • 'methylation': -[MEASURED_DIFFERENTIAL_METHYLATION_ASmMR]-> MethylationRegion x = methylation_diff, y = -log10(q_value), labels = gene symbol (joined via METHYLATED_IN_MGmMR back to MGene for labeling) Magnitude filter: methylation_diff_threshold (default 10.0 = 10%)

  • 'abundance': -[MEASURED_DIFFERENTIAL_ABUNDANCE_ASmO]-> Organism x = log2fc, y = -log10(significance), labels = organism name Magnitude filter: log2fc_threshold (default 1.0 = 2-fold) Significance is method-aware: DESeq2 rows use adj_p_value, ANCOM-BC rows use q_value.

Points are colored by significance:

  • Red: positive direction (upregulated / hypermethylated / increased)

  • Blue: negative direction (downregulated / hypomethylated / decreased)

  • Gray: not significant

Returns a markdown summary, an inline PNG image (if small enough), and the saved file path. Designed to handle assays with thousands of features without timing out.

Inputs: assay_id (required), top_n, data_type, session_id, +6 more.

end_sessionA
Idempotent

End a session immediately, discarding its output-directory setting and all plots it holds. Optional — sessions also expire on their own. Call it when the user is done, to free server memory promptly. After this, a new create_session() is needed before further tool calls.

Inputs: session_id.

fetch_plotA
Read-onlyIdempotent

Re-fetch the PNG bytes of a plot previously generated IN THIS SESSION.

WHEN TO USE THIS TOOL: Call this when you need the canonical PNG bytes for a plot that's already been generated. Common cases:

  • The inline image in the original plot tool response was corrupted or didn't render in the client.

  • You need the bytes for a downstream step (e.g. embedding in a transcript, saving to a side file, base64-encoding for an external API).

  • The user asked to see the plot again without re-running the analysis.

WHAT THIS TOOL DOES NOT DO: It does NOT re-render the plot. It returns the same bytes that were registered when the plot was originally generated. If the underlying data has changed, re-run the plot tool itself (create_volcano_plot, create_venn_diagram); don't expect fetch_plot to pick up new data.

EQUIVALENT RESOURCE URI: This tool returns the same bytes that resources/read would return for plot://<session_id>/<filename>. Use whichever path your client supports better — resources for clients that render them well, this tool for clients that don't.

REGISTRY BOUNDS: Each session holds its last 8 plots (FIFO eviction). Older plots, and plots from other or expired sessions, return a clear "not in registry" error and need to be regenerated by re-running the source plot tool under the current session.

Inputs: filename (required), session_id.

find_common_de_genes_overlapping_dm_regionsA
Read-onlyIdempotent

USE THIS TOOL (not the query tool) for any "expression-methylation coupling", "classical epigenetic silencing", "DE genes that are also DM", "downregulated genes with promoter hypermethylation", or any cross-type intersection between differential expression and differential methylation. Falling back to query for this category reproduces the four-quadrant intersection logic this tool already does correctly (parallel DE+DM fetches across DIFFERENT assays, pooled-methylation aggregation when multiple methylation assays are passed as a list, MethylationRegion location filtering on the DM side, up_hyper/up_hypo/down_hyper/down_hypo direction categorization) and loses the four-quadrant markdown summary and the inline combined CSV.

Find differentially expressed genes that overlap with differentially methylated regions.

This cross-analysis tool:

  1. Gets DE genes from the expression assay (filtered by log2fc and adj_p thresholds)

  2. Gets genes associated with DM regions from the methylation assay(s) (filtered by methylation_diff, q_value, and any MethylationRegion location filters: in_promoter, in_exon, in_intron, dist_to_feature_max). If methylation_assay_id is a list, the methylation evidence is POOLED across the listed assays before the intersection — a gene is treated as hypermethylated if it passes the threshold in ANY of the pooled assays.

  3. Finds the intersection (genes that are BOTH differentially expressed AND differentially methylated)

  4. Reports the overlap categorized by direction (up+hyper, up+hypo, down+hyper, down+hypo)

For the classical epigenetic-silencing question — promoter hypermethylation reducing expression — pass in_promoter=True. When a study has replicate methylation assays (e.g. OSD-48 has two methylKit assays for the same Space Flight vs. Ground Control comparison), pass them as a list to capture the combined methylation evidence on the methylation side of the intersection.

Inputs: expression_assay_id (required), methylation_assay_id (required), in_exon, in_intron, +7 more.

find_common_differentially_abundant_organismsA
Read-onlyIdempotent

USE THIS TOOL (not the query tool) for any "common differentially abundant organisms across assays", "organisms increased in BOTH assays", "shared abundance signals across methods" (e.g. DESeq2 vs ANCOM-BC concordance), or any cross-assay abundance intersection question. Falling back to query for this category reproduces the per-assay fetch + inner-join logic this tool already does correctly (parallel fetches, method-aware significance filtering, lnfc handling that doesn't drop DESeq2 rows, separate increased vs. decreased intersections) and loses the formatted markdown + inline CSV side-channel and the assay-reference legend.

Find common differentially abundant organisms across multiple assays.

Useful for comparing results from different analysis methods (e.g., DESeq2 vs ANCOM-BC 1 vs ANCOM-BC 2) to identify organisms consistently detected as differentially abundant.

Direction (increase vs. decrease) and ranking use log2fc, which is populated for BOTH DESeq2 and ANCOM-BC edges in the GeneLab KG. log2fc is therefore the universal magnitude filter (log2fc_threshold); lnfc is ANCOM-BC-only and would null-filter every DESeq2 row if used for direction.

Significance filtering is method-aware:

  • DESeq2 edges populate adj_p_value (not q_value); the adj_p_threshold applies.

  • ANCOM-BC edges populate q_value (not adj_p_value); the q_value_threshold applies. Each row is kept if its populated significance field meets the matching threshold.

Magnitude filtering:

  • log2fc_threshold (default 0.0) applies to every row, since log2fc is populated for both methods.

  • lnfc_threshold (default None = no filter) is method-aware: when set, it requires |lnfc| >= lnfc_threshold on rows where lnfc is populated. Rows where lnfc is null (i.e., DESeq2 rows) are not affected by this filter.

This function:

  1. Takes a list of assay IDs as input (2 or more)

  2. Gets ALL organisms passing the magnitude and method-aware significance filters for each assay

  3. Inner joins among increased and among decreased abundance organisms

  4. Returns markdown tables showing common organisms and their log2fc values

Inputs: assay_ids (required), session_id, lnfc_threshold, adj_p_threshold, +2 more.

find_common_differentially_expressed_genesA
Read-onlyIdempotent

USE THIS TOOL (not the query tool) for any "common DEGs across assays", "genes upregulated in BOTH assays", "shared up/downregulated genes", or any cross-assay DE intersection question. Falling back to query for this category reproduces the per-assay fetch + inner-join logic this tool already does correctly (parallel fetches via the driver's connection pool, |log2fc| > threshold filtering, separate up vs. down intersections) and loses the formatted markdown tables, the inline CSV side-channel, and the assay-reference legend.

Find common differentially expressed genes across multiple assays.

This function:

  1. Takes a list of assay IDs as input (2 or more)

  2. Gets ALL genes with |log2fc| > threshold for each assay

  3. Inner joins among the upregulated genes and among the downregulated genes

  4. Returns a markdown table with columns: gene, assay_1, assay_2, ..., assay_n showing log2fc values

Inputs: assay_ids (required), session_id, adj_p_threshold, log2fc_threshold.

find_common_differentially_methylated_regionsA
Read-onlyIdempotent

USE THIS TOOL (not the query tool) for any "common DMRs across assays", "genes hypermethylated in BOTH assays", "shared hyper/hypomethylated regions", or any cross-assay methylation intersection question — including promoter/exon/intron-filtered and distance-bounded variants. Falling back to query for this category reproduces the per-assay fetch + inner-join logic this tool already does correctly (parallel fetches, MethylationRegion location filtering applied during the Cypher so the common set reflects the filtered universe, methylation_diff/q_value thresholds, separate hyper vs. hypo intersections) and loses the formatted markdown + inline CSV side-channel and the assay-reference legend.

Find common differentially methylated genes across multiple assays.

This function:

  1. Takes a list of assay IDs as input (2 or more)

  2. Gets ALL genes associated with differentially methylated regions for each assay, applying the methylation_diff threshold, q_value threshold, and any MethylationRegion location filters (in_promoter, in_exon, in_intron, dist_to_feature_max)

  3. Inner joins among hypermethylated genes and among hypomethylated genes

  4. Returns markdown tables showing common genes and their methylation_diff values

Use the location filter parameters rather than post-filtering — they are applied during the Cypher query so the common gene set reflects the filtered universe correctly.

Inputs: assay_ids (required), in_exon, in_intron, session_id, +4 more.

find_differentially_abundant_organismsA
Read-onlyIdempotent

USE THIS TOOL (not the query tool) for any "differentially abundant organisms", DESeq2/ANCOM-BC abundance, or "increased/decreased abundance" question for a single assay.

The query tool can express the same Cypher, but using it for this category loses the formatted markdown tables, the inline CSV side-channel, the method-aware significance filtering (DESeq2 adj_p_value vs. ANCOM-BC q_value), and the safe lnfc handling that avoids silently dropping DESeq2 rows (where lnfc IS NULL would fail a naive lnfc > 0 filter).

Return the top-N organisms with increased and decreased differential abundance for a given assay_id.

Direction (increase vs. decrease) and ranking use log2fc, which is populated for BOTH DESeq2 and ANCOM-BC abundance edges in the GeneLab KG. log2fc is therefore used as the universal direction/ordering field and as the default magnitude filter.

The lnfc property is only populated for ANCOM-BC edges (DESeq2 leaves it null). It is returned in the result for reference and can be used as an additional magnitude filter via the lnfc_threshold parameter. log2fc is the direction filter because it is populated for both DESeq2 and ANCOM-BC rows; using lnfc for direction would null-filter every DESeq2 row out of the result.

Significance filtering is method-aware:

  • DESeq2 edges populate adj_p_value (not q_value); the adj_p_threshold applies.

  • ANCOM-BC edges populate q_value (not adj_p_value); the q_value_threshold applies. Each row is kept if its populated significance field meets the matching threshold.

Magnitude filtering:

  • log2fc_threshold (default 0.0) applies to every row, since log2fc is populated for both methods.

  • lnfc_threshold (default None = no filter) is method-aware: when set, it requires |lnfc| >= lnfc_threshold on rows where lnfc is populated. Rows where lnfc is null (i.e., DESeq2 rows) are not affected by this filter. Set lnfc_threshold to a positive number to add an ANCOM-BC-specific magnitude filter on top of log2fc.

This tool runs two queries on the GeneLab KG:

  1. Top-N organisms with increased abundance (log2fc > log2fc_threshold, significance and optional lnfc filters met, highest log2fc first)

  2. Top-N organisms with decreased abundance (log2fc < -log2fc_threshold, significance and optional lnfc filters met, lowest log2fc first)

Results include organism name, log2fc, lnfc, q-value, adj-p-value, and group means and standard deviations.

Inputs: assay_id (required), top_n, session_id, lnfc_threshold, +3 more.

find_differentially_expressed_genesA
Read-onlyIdempotent

USE THIS TOOL (not the query tool) for any "up/down-regulated genes", "DEGs", or "differential expression" question for a single assay.

The query tool can express the same Cypher, but using it for this category loses the formatted markdown tables, the inline CSV side-channel, the proper adj_p_value handling, and the parallel execution of the count queries this tool already provides correctly.

Return the top-N up- and down-regulated genes for a given assay_id.

This tool runs two queries on the GeneLab KG:

  1. Top-N upregulated genes (log2fc > 0, adj_p_value <= adj_p_threshold, highest log2fc first)

  2. Top-N downregulated genes (log2fc < 0, adj_p_value <= adj_p_threshold, lowest log2fc first)

Returning all passing rows: Pass top_n=None to return ALL rows that pass the filters rather than a top-N ranking. Use this when the user asks for "all significantly up/downregulated genes" or wants the complete filtered set as CSV.

Results include gene symbol, gene name, log2 fold change, adjusted p-value, and group means and standard deviations for each condition.

Inputs: assay_id (required), top_n, session_id, adj_p_threshold.

find_differentially_methylated_regionsA
Read-onlyIdempotent

USE THIS TOOL (not the query tool) for any "hyper/hypo-methylated regions", "DMRs", or "differential methylation" question — including all-rows requests, promoter/exon/intron-filtered methylation queries, and pooling methylation across replicate assays. Falling back to query for this category reproduces the work this tool already does (proper IS-NOT-NULL guards, gene-symbol join, parallel count queries, location filtering, deterministic CSV emission) and loses the formatted markdown

  • inline CSV side-channel.

Return hyper- and hypo-methylated regions for one or more assays.

This tool runs two queries on the GeneLab KG:

  1. Hypermethylated regions (methylation_diff > methylation_diff_threshold, q_value <= q_value_threshold, highest first)

  2. Hypomethylated regions (methylation_diff < -methylation_diff_threshold, q_value <= q_value_threshold, lowest first)

Pooling across assays: Pass a list to assay_id to pool results across multiple methylation assays (the Cypher uses a.identifier IN $assay_ids). Common use case: a study has 2+ methylation assays representing replicate runs of the same comparison, and the user wants the combined evidence rather than per-assay tables. The output adds an assay_id column so each row's source is visible.

Returning all passing rows: Pass top_n=None to return ALL rows that pass the filters rather than a top-N ranking. Use this when the user asks for "all hypermethylated promoter regions" or wants the complete filtered set as CSV. To keep the response readable when the full set is large, the inline markdown table is capped at the first 100 rows and a note is shown; the CSV contains every row.

MethylationRegion location filters (in_promoter, in_exon, in_intron, dist_to_feature_max) are applied DURING the Cypher query. This means when a user asks for "top hypermethylated regions in the promoter", pass in_promoter=True and the tool will correctly rank within the promoter universe. Do NOT post-filter the unfiltered top-N — that produces wrong results because regions outside the filter (e.g. non-promoter regions) occupy slots in the unfiltered top-N and displace correctly-ranked filtered regions. Multiple filters combine with AND, so in_promoter=True with in_intron=False returns promoter regions that are not intronic.

WHEN TO USE THIS TOOL vs. direct Cypher via the query tool: Use THIS tool for any "hyper/hypo methylated regions" question, including pooled-across-assays, all-passing-rows, and filter-by-location variants. It produces formatted markdown tables AND an inline CSV that the user can save directly. Falling back to direct Cypher loses the formatted output and the CSV.

Inputs: assay_id (required), top_n, in_exon, in_intron, +5 more.

get_neo4j_schemaA
Read-onlyIdempotent

List all nodes, their attributes and their relationships to other nodes in the neo4j database. If this fails with a message that includes "Neo.ClientError.Procedure.ProcedureNotFound" suggest that the user install and enable the APOC plugin.

Inputs: session_id.

get_node_metadataB
Read-onlyIdempotent

Get metadata for all nodes from MetaNode nodes in the knowledge graph.

Inputs: session_id.

get_output_directoryA
Read-onlyIdempotent

Return the currently-configured output directory for this session.

Returns the path previously set by set_output_directory in the same session, or a note explaining that no path has been set yet (and how to set one).

Inputs: session_id.

get_relationship_metadataB
Read-onlyIdempotent

Get descriptions of properties of all relationships in the knowledge graph.

Inputs: session_id.

get_save_scriptA
Read-onlyIdempotent

Return guidance for saving a plot generated in THIS SESSION to the user's local filesystem.

WHEN TO USE THIS TOOL: Call this only when the user explicitly asks for save guidance for a specific plot — for example, "how do I save the volcano plot to my Downloads folder?" or "I can't right-click — give me another way to save the plot." By default plot tools (create_volcano_plot, create_venn_diagram) return only a SHORT save hint to keep response sizes manageable. The detailed save options are delivered on demand via this tool, so they don't burn conversation context unless the user actually wants them.

HOW IT WORKS: Each plot tool registers the PNG bytes of the plot it generated in the calling session's registry (up to the last 8 plots; older entries are evicted FIFO). Calling this tool with the plot's suggested filename returns a markdown block with three save options:

  • Option A (right-click save on the inline image)

  • Option B (ask your LLM client to save via filesystem access, optionally re-fetching the canonical bytes through fetch_plot or the plot:// resource if the inline image was corrupted)

  • Option C (fetch the canonical PNG bytes via resources/read on the plot://<session_id>/ URI for clients that support MCP resources)

The response itself contains no PNG bytes — only references to the plot:// resource URI and the fetch_plot tool, both of which deliver the bytes through a separate request.

LISTING AVAILABLE PLOTS: Call this tool with no filename argument to list the filenames of all plots currently held in this session's registry. Useful when the user asks for save guidance but doesn't remember which plot they want.

Inputs: filename, session_id.

get_study_infoA
Read-onlyIdempotent

USE THIS TOOL (not the query tool) for any study-metadata question: "what assays does study X have", "tell me about OSD-267", project title, description, host organism, missions, factor space, or any inventory of a study's assays. Falling back to query for these reproduces the work this tool already does and loses the formatted markdown + inline CSV side-channel.

Return detailed information about a study, including its assays with their technology and measurement types.

This tool queries the GeneLab KG for:

  1. Study metadata (name, project title, description, organism, etc.)

  2. All assays for the study with their technology, measurement type, differential analysis method, factors, and materials

  3. Associated missions

For example, OSD-267 should return that it has both 16S and ITS amplicon sequencing data.

Inputs: study_id (required), session_id.

queryA
Read-onlyIdempotent

FALLBACK Cypher executor. Use this ONLY when no specialist tool covers the question.

DO NOT call this tool when the question matches one of these patterns — call the named tool instead, EVEN IF you think Cypher would be more flexible:

  • "up/down-regulated genes", "DEGs", "differential expression", "log2fc rankings", "top N up/downregulated genes for assay X" → find_differentially_expressed_genes(assay_id=...)

  • "hyper/hypo-methylated regions", "DMRs", "methylation_diff", "hypermethylated promoter regions", "all DMRs passing q<0.05", pooling methylation across replicate assays → find_differentially_methylated_regions(assay_id=...)

  • "differentially abundant organisms", DESeq2/ANCOM-BC abundance, "increased/decreased abundance for assay X" → find_differentially_abundant_organisms(assay_id=...)

  • study metadata, what assays a study has, study factors/materials, project title, description, host organism/strain → get_study_info(study_id=...)

  • factor-pair → assay-id resolution (e.g. "give me the assay for Space Flight,Carcass vs Ground Control,Carcass in OSD-48") → select_assays(study_id=..., selection=...)

  • "what groups / conditions / control and experimental (treatment) groups are in study X", "what comparisons does OSD-48 have", "which factors were compared" — any question about the groups a study contains, even with no factor pair named → select_assays(study_id=...) (list mode; omit selection)

  • common DEGs/DMRs/DA organisms across multiple assays, intersections → find_common_differentially_expressed_genes(assay_ids=[...]) → find_common_differentially_methylated_regions(assay_ids=[...]) → find_common_differentially_abundant_organisms(assay_ids=[...])

  • DE genes overlapping DM regions, expression-methylation coupling, classical epigenetic silencing analysis → find_common_de_genes_overlapping_dm_regions(...)

  • listing nodes / properties / relationships in the KG → get_neo4j_schema(), get_node_metadata(), get_relationship_metadata()

If you only have a study identifier and need assay IDs, call select_assays or get_study_info FIRST; do not write Cypher to discover assay IDs.

The specialist tools return formatted markdown tables AND an inline CSV side-channel that this query tool does not produce. Falling back to query for the categories above also loses the parallel multi-query execution, the method-aware significance filtering (DESeq2 adj_p_value vs. ANCOM-BC q_value), the region-vs-gene aggregation, and the MethylationRegion location filter plumbing the specialists already implement correctly.

Only call this tool for ad-hoc Cypher that the specialist tools cannot express: schema exploration, custom multi-hop traversals, exotic aggregations, or one-off counts the specialists don't expose.

OUTPUT FORMAT - CRITICAL: The response begins with a total_rows: N header followed by rows: and then the JSON array of records. When reporting counts to the user (e.g. "how many hypermethylated regions are there"), ALWAYS use total_rows, NEVER count rows visible in the JSON array. Large results may be truncated by the MCP transport and stored to a side-file, leaving only a partial preview of the array — but the total_rows count is computed server-side from the materialized result before any truncation and is always accurate. For aggregate queries (RETURN count(*)) total_rows will be 1 and the count itself lives in the row's count(*) field.

EDGE PROPERTIES - CRITICAL: Many relationships in this knowledge graph have properties stored as edge attributes (data ON the relationship itself).

MEASURED_DIFFERENTIAL_EXPRESSION_ASmMG: log2fc, adj_p_value, group_mean_1, group_stdev_1, group_mean_2, group_stdev_2 MEASURED_DIFFERENTIAL_METHYLATION_ASmMR: methylation_diff, q_value, group_mean_1, group_stdev_1, group_mean_2, group_stdev_2 MEASURED_DIFFERENTIAL_ABUNDANCE_ASmO: log2fc, lnfc, q_value, adj_p_value, group_mean_1, group_stdev_1, group_mean_2, group_stdev_2

ABUNDANCE EDGE - METHOD-AWARE FIELDS (CRITICAL for correct queries): The MEASURED_DIFFERENTIAL_ABUNDANCE_ASmO edge stores different fields depending on which differential analysis method produced the row. Use log2fc (not lnfc) for direction and ranking, since it is populated for BOTH methods:

  • DESeq2 edges: log2fc populated, lnfc = null, adj_p_value populated, q_value = null

  • ANCOM-BC edges: log2fc populated, lnfc populated, adj_p_value = null, q_value populated

To filter by significance in a method-agnostic way, OR both fields together: WHERE r.log2fc > 0 AND ( (r.adj_p_value IS NOT NULL AND r.adj_p_value <= 0.05) OR (r.q_value IS NOT NULL AND r.q_value <= 0.05) )

Filtering on r.lnfc > 0 will silently drop every DESeq2 row because Cypher's null > 0 evaluates to null and fails the WHERE clause. If you want to use lnfc as an ANCOM-BC-specific magnitude filter alongside log2fc-based direction, write the clause defensively: AND (r.lnfc IS NULL OR abs(r.lnfc) >= 0.5) This applies the lnfc threshold only to rows where lnfc is populated (ANCOM-BC) and leaves DESeq2 rows untouched.

RELATIONSHIP DIRECTIONS (always use directed arrows in queries): (Assay)-[:MEASURED_DIFFERENTIAL_EXPRESSION_ASmMG]->(MGene) (Assay)-[:MEASURED_DIFFERENTIAL_METHYLATION_ASmMR]->(MethylationRegion) (Assay)-[:MEASURED_DIFFERENTIAL_ABUNDANCE_ASmO]->(Organism) (MGene)-[:METHYLATED_IN_MGmMR]->(MethylationRegion) (Study)-[:PERFORMED_SpAS]->(Assay) (Mission)-[:CONDUCTED_MIcS]->(Study)

NODE PROPERTIES - CRITICAL (use EXACTLY these property names, no others exist): MGene: identifier, symbol, name, organism, taxonomy MethylationRegion: identifier, name, chromosome, start, end, in_promoter, in_exon, in_intron, dist_to_feature Assay: identifier, name, technology, measurement, differential_analysis_method, factors_1, factors_2, material_1, material_2, material_id_1, material_id_2, material_name_1, material_name_2, factor_space_1, factor_space_2 Study: identifier, name, project_title, project_type, description, organism, taxonomy, host_organism, host_strain Mission: identifier, name, flight_program, space_program, start_date, end_date Organism: identifier, name

COMMON PROPERTY NAME MISTAKES - NEVER USE THESE: WRONG: mg.gene_symbol RIGHT: mg.symbol WRONG: mg.gene_name RIGHT: mg.name WRONG: g.gene_symbol RIGHT: g.symbol WRONG: g.gene_name RIGHT: g.name

Inputs: query (required), params, session_id.

select_assaysA
Read-onlyIdempotent

USE THIS TOOL (not the query tool) for ANY question about the groups a study contains, and to resolve a factor-pair condition into the matching assay identifier(s):

  • "What groups / conditions / control and experimental (treatment) groups are in OSD-48?", "which comparisons or factors does this study have?", "what was compared against what?" — call with just study_id (list mode). The numbered factor menu it returns IS the list of groups: each entry is one experimental group (a set of factor values such as "Space Flight,Carcass"), and each assay is a comparison of two such groups (condition 1 vs condition 2, e.g. experimental vs control). Never use query for this.

  • "Give me the assay for Space Flight,Carcass vs Ground Control,Carcass" — call with study_id and selection to resolve that factor pair (e.g. "2,1") into assay identifier(s).

Falling back to query for this category loses the numbered factor menu, the per-match technology/measurement/method columns, and the next-step suggestions this tool emits.

List and select assays for a study and render the response in markdown format.

First call (selection=None):

  • If study_id missing, prompt for one (e.g., 'OSD-253').

  • Build a list of unique factor arrays across all assays.

  • Return a numbered menu as a markdown table.

Second call (selection='i,j,k,l,...,m,n'):

  • Pairs consecutive indices: (i,j), (k,l), ..., (m,n)

  • Must provide an even number of indices

  • For each pair, returns the matching assay(s) with technology, measurement, differential analysis method, and material columns so the assistant can pick the right assay for a downstream question (e.g., RNA-Seq for DE genes, WGBS for DM regions, amplicon for organism abundance) WITHOUT issuing a follow-up Cypher query.

Inputs: study_id, selection, session_id.

set_output_directoryA
Idempotent

Configure the output directory for files generated in THIS SESSION.

WHEN TO USE THIS TOOL: Call this tool at the START of a session (right after create_session), before any tool that produces a downloadable file (create_volcano_plot, create_venn_diagram, or any tool that emits a CSV). The path you specify is where the user wants finished files to end up on THEIR OWN local machine.

WHAT IT DOES: Stores the provided path string in the server's session-scoped state (keyed on your session_id — other sessions cannot see or change it). Every subsequent file-producing tool in this session uses this path:

  • As the user-facing save location shown in the response summary.

  • As the default target path in the save guidance emitted with every plot.

  • If the server is running locally (stdio transport), the server ALSO writes the file directly to this path.

IMPORTANT — DEPLOYMENT REALITY: When this MCP server is deployed remotely (ECS Fargate or any other container service), it runs in a container whose filesystem is NOT reachable from the user's machine. The server CANNOT write a file directly to the user's local disk over the network — no MCP server in a container can. The path you set here is a suggestion that propagates through the response in three ways, any of which lets the user save the file locally: (a) The plot is returned inline as ImageContent and renders in any MCP client that displays images (Claude Desktop, Cursor, Cline, Claude.ai web, ChatGPT, Gemini, etc.). The user can right-click and "Save Image As" — most clients default to the user's Downloads folder, which is usually what was asked for. (b) The path you set appears in the save guidance in the response. LLM clients with local filesystem access (Claude Code, Cursor, Cline, Claude Desktop with a filesystem MCP server) can write the file at exactly this path, re-fetching the canonical bytes via fetch_plot or the plot:// resource if needed. (c) Users without LLM-mediated filesystem access can save the inline image or the inline CSV text themselves.

VALIDATION: The path is stored as-is (the server does not verify it exists on the user's machine — it has no way to do so from inside a container). If you pass a relative path or an obviously malformed string the server will accept it; the failure will surface when the user tries to save the file locally.

Inputs: path (required), session_id.

visualize_schemaB
Read-onlyIdempotent

Prompt for visualizing the knowledge graph schema using a Mermaid class diagram.

Inputs: session_id.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A3.7/5.0

    Scored across 24 tools

    Disambiguation4/5

    The find_* specialists are cleanly separated by data type (expression/methylation/abundance) and by scope (single vs common vs cross-type overlap), and `query` has explicit routing rules to prevent misuse. However, the schema/metadata cluster (get_node_metadata, get_neo4j_schema, get_relationship_metadata) and the plot-saving pair (fetch_plot, get_save_script) overlap enough that selection could be fuzzy. The lengthy descriptions largely resolve this, so only a couple of pairs are confusable.

    Naming Consistency4/5

    Consistent snake_case throughout, and most names follow a verb_noun pattern (get_study_info, create_session, find_differentially_expressed_genes, set_output_directory, create_venn_diagram). Minor deviations exist: `query` is a bare verb with no object, and `visualize_schema`/`clean_mermaid_diagram` break the get/find/create cadence. Overall predictable with small inconsistencies.

    Tool Count3/5

    At 24 tools the surface is heavy, sitting in the borderline range. Most clusters (7 find_* analyses, session/output management, schema metadata) are justified by the genuinely broad domain, but a few tools like create_chat_transcript, clean_mermaid_diagram, and visualize_schema feel auxiliary to the core KG-analysis purpose. The count is reasonable but slightly overweight.

    Completeness4/5

    Coverage is strong: single-assay and cross-assay analyses for all three differential data types, a DE/DM coupling tool, study/assay resolution, schema introspection, plotting, and a general Cypher fallback. The main gap is study discovery — there is no tool to search or list studies, so an agent must already know a study_id (e.g. OSD-267) or fall back to raw Cypher to find one.

    Maintenance

    ActivityMaintained
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • F
      license
      Not graded
      quality
      D
      maintenance
      Enables storage and retrieval of knowledge in a graph database format, allowing users to create, update, search, and delete entities and relationships in a Neo4j-powered knowledge graph through natural language.
      5
      -
    • A
      license
      Not graded
      quality
      D
      maintenance
      Enables users to write and execute SPARQL queries against open-access SPARQL endpoints by providing relevant query examples, schema information, and endpoint metadata. Supports querying biological databases like UniProt and Bgee through natural language interactions.
      12
      MIT
    • A
      license
      Not graded
      quality
      D
      maintenance
      Enables AI assistants to interact with Gremlin-compatible graph databases through natural language, supporting schema discovery, complex graph queries, relationship analysis, and data import/export operations.
      30 npm
      9
      MIT
    • A
      license
      Not graded
      quality
      D
      maintenance
      Enables AI assistants to interact with Neo4j graph databases through natural language, supporting Cypher queries, schema management, data manipulation, and graph algorithms.
      MIT