Skip to main content
Glama

Agentic Metabolic Systems Biology - Stateful COBRApy via MCP & SKILLS.md

GSoC 2026 · NRNB (National Resource for Network Biology) · Project #280 (Self-Project)

A portable, deterministic bridge between Large Language Models and genome-scale metabolic modeling (GEM) tooling - built on the Model Context Protocol (MCP) for tool discovery/execution and the SKILLS.md standard for encoding expert workflows as reusable, semantic execution contracts.

This repository is the foundational boilerplate for the project: a stateful FastMCP server wrapping COBRApy, a sample SKILLS.md workflow, a fully containerized one-click deployment, and a test suite that doubles as a working proof-of-concept report.


Why this exists

Genome-scale metabolic models are computationally powerful but operationally fragile: COBRApy, CarveMe, and Neo4j each have their own idiosyncratic APIs, and naively feeding an LLM full model dumps or library docs either overflows its context window or invites it to hallucinate a metabolic pathway that doesn't exist. This project's answer is architectural, not prompt-based:

  • MCP is the kitchen — a slim, dynamically-discoverable set of tools the agent can call, with the underlying biological objects (models, solvers) kept server-side.

  • SKILLS.md is the recipe book — the expert standard operating procedure (load → validate gene → knock out → re-optimize → compare) that keeps the LLM as an orchestrator of deterministic linear-programming calls, never the source of a numeric result itself.

Related MCP server: MCP Python Interpreter

Architecture

                         Application Host Process
   ┌────────────────────────────────────────────────────┐
   │   LLM Agent (e.g. OpenCode)                         │
   │        │                                            │
   │        │  reads workflow contract                   │
   │        ▼                                            │
   │   skills/fba_workflow.md  (SKILLS.md)               │
   │        │                                            │
   │        │  emits tool calls (JSON-RPC 2.0)            │
   │        ▼                                            │
   │   MCP Client  ─────────────────stdio/HTTP──────────►│──┐
   └────────────────────────────────────────────────────┘  │
                                                             ▼
                                          ┌─────────────────────────────────┐
                                          │  FastMCP Server (server.py)      │
                                          │  ─────────────────────────────   │
                                          │  SESSIONS: dict[session_id ->    │
                                          │             ModelSession]        │
                                          │                                   │
                                          │  tools:                          │
                                          │   load_model                     │
                                          │   knockout_gene                  │
                                          │   run_fba                        │
                                          │   get_flux_distribution          │
                                          │   list_genes                     │
                                          │   list_sessions / reset_session  │
                                          │                                   │
                                          │  COBRApy  ──►  GLPK/CBC solver    │
                                          └─────────────────────────────────┘

Host - the LLM application (e.g. an OpenCode agent) that decides when to call a tool. Client - the MCP client embedded in the host, speaking JSON-RPC 2.0 over stdio (or streamable-HTTP inside Docker). Server - server.py: a FastMCP process that owns the COBRApy models and the solver, and exposes a small, versioned tool surface.

Stateful, URI-addressable models

The proposal's central design constraint is that a GEM must never be serialized into the LLM's context window - a genome-scale SBML file can be tens of megabytes and instantly blow the token budget. Instead:

  1. load_model reads the model once, server-side, and returns only a session_id plus a metabolic://models/{session_id} resource URI and small summary metadata (reaction/gene/metabolite counts).

  2. Every subsequent tool call (knockout_gene, run_fba, ...) takes that session_id and mutates or queries the same in-memory cobra.Model object held in the server's SESSIONS registry.

  3. A gene knockout applied in one conversational turn is therefore still in effect the next time the agent calls run_fba with that session_id - no reload, no re-serialization, no context bloat.

  4. Only scalars (objective value, solver status) or small top-N summaries are ever returned to the agent — the full flux vector is available on request via get_flux_distribution, but is not sent by default.

This in-memory registry is intentionally simple (a Python dict) for this boilerplate. The proposal's noted limitation - a server restart clears all sessions - is real; a persistence layer (e.g. pickling ModelSession objects to the model_data Docker volume) is documented future scope, not implemented here.

Repository layout

.
├── Dockerfile              # multi-stage build: builder (solver deps) -> slim runtime
├── docker-compose.yml       # one-click orchestration
├── requirements.txt
├── server.py                 # FastMCP server + stateful COBRApy tools
├── skills/
│   └── fba_workflow.md      # SKILLS.md execution contract for FBA + knockout
└── tests/
    └── test_server.py       # unit tests, MCP protocol integration test, PoC metrics

Tools exposed by the server

Tool

Purpose

load_model(model_name, sbml_path)

Load a built-in model (textbook / ecoli_core, salmonella) or a custom SBML file. Returns session_id + summary metadata.

knockout_gene(session_id, gene_id)

Knock out a gene in the session's model; persists for future calls. Errors deterministically on an unknown gene.

run_fba(session_id)

Runs FBA on current model state; returns only solver status + objective value.

get_flux_distribution(session_id, top_n)

Opt-in detail: top-N reactions by

list_genes(session_id, limit)

Grounds the agent in real gene IDs before a knockout, preventing hallucinated IDs.

list_sessions()

Lists all active server-side sessions.

reset_session(session_id)

Discards a session's in-memory state.

Built-in models (textbookE. coli core, salmonella) are loaded from COBRApy's bundled local data files, so load_model works fully offline - no BiGG/BioModels network call is required, which matters inside an air-gapped Docker container.

The SKILLS.md contract

skills/fba_workflow.md defines the FBA + gene-knockout workflow as YAML-frontmatter metadata (inputs, outputs, tool dependencies, execution constraints, failure-recovery rules) followed by a plain-language procedure. Two constraints worth highlighting:

  • The agent must capture the wild-type objective value via run_fba before calling knockout_gene, so there is always a baseline to compare against.

  • The agent must confirm a gene ID against list_genes before calling knockout_gene - a gene ID is never guessed.

This file is mounted read-write into the container (./skills:/app/skills) so new workflows can be authored or edited without rebuilding the image — the "dynamic SKILLS.md hot reload" behavior described in the proposal.

Quickstart

git clone repo_url.git
cd gem-mcp
docker compose up --build

This builds the multi-stage image (solver dependencies compiled in a builder stage, copied into a slim runtime stage) and starts the FastMCP server listening on stdio by default. To expose it over HTTP instead (e.g. for a containerized agent host to reach it across the Docker network), override the command:

docker compose run --rm -p 8000:8000 cobrapy-mcp \
  python server.py --transport streamable-http --host 0.0.0.0 --port 8000

Option B - Local Python

python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
python server.py                 # stdio transport, for a local MCP host
# or:
python server.py --transport streamable-http --port 8000

Running the tests / PoC metrics

pip install -r requirements.txt
pytest tests/test_server.py -v          # unit tests + real MCP client/server round trip

python tests/test_server.py             # prints PoC metrics, e.g.:
# === E. coli core model — PoC metrics ===
# Reactions:   95
# Metabolites: 72
# Genes:       137
# Wild-type growth rate (1/hr): 0.873922
# Top 5 fluxes (wild type): ATPS4r +45.51, CYTBD +43.60, NADH16 +38.53, ...
# Knockout gene: b1241
# Post-knockout growth rate (1/hr): 0.873922
# Growth ratio (KO / WT): 1.0000

The test suite includes:

  • Unit tests against the tool functions directly (session creation, invalid gene/session handling, knockout persistence across separate calls).

  • An in-process MCP integration test using FastMCP's Client, which drives the exact same JSON-RPC path a real agent host would use — proving the tools are correctly registered, not just correct as plain functions.

  • A PoC metrics report (python tests/test_server.py) that loads the E. coli core model, runs a baseline FBA, shows the top fluxes, performs a knockout, and reports the resulting growth ratio — the same numbers you'd want in a GSoC progress update.

F
license - not found
Not graded
quality - not tested
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

View all related MCP servers

Related MCP Connectors

  • AI-powered bioprotocol optimization — generate, search, and manage lab protocols via MCP

  • A comprehensive Model Context Protocol (MCP) server that enables AI assistants to interact with yo…

  • Calibrated world model for AI agents. 40 tools: world state, markets, trading. Kalshi + Polymarket.

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/praneeshlabs/gem-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server