Skip to main content
Glama

open-med-mcp (OMM) is a Model Context Protocol server for medical image analysis. It gives AI coding agents (Claude Code, Codex CLI, Claude Desktop, Cursor, ...) tools to inspect a CT/MRI/X-ray, run segmentation and other models, view and measure the result, and write a report — all on your own machine.

Beyond segmentation it covers classification, detection, vision-language questions, radiomics, and computable clinical criteria (RECIST 1.1, Fleischner, Lung-RADS, LI-RADS, TI-RADS, Agatston). Three pillars:

pillar

what it means

1. Containerized specialised models

Every model is an adapter with a manifest, a run.py and a Dockerfile, speaking one tiny job-directory contract. Run it locally (pip extra), in Docker (GHCR images) or in Apptainer on an HPC cluster - the agent does not care which. Ships with MedSAM2, SAM 2.1, VoxTell (free-text prompts), TotalSegmentator, lungmask, HD-BET, SynthStrip (official FreeSurfer image), nnU-Net (any trained model), MONAI Model Zoo bundles, TorchXRayVision and a classical baseline; adding your own model is a folder with three files, and existing third-party images can be wrapped with a command template.

2. Preset / custom guidelines

Markdown protocols with YAML front matter that tell an agent how to do a task well (which model, which window, what to check, what to report). Presets ship with the package; drop your own into a folder to override or extend them. They are exposed as MCP prompts and resources.

3. Modular, code-customizable viewer

For the agent, render_view returns PNGs (single slice, three planes, montage) with native-voxel coordinate grids. For you, export_viewer writes a self-contained interactive HTML viewer (cine, overlay toggle, zoom, click/drag for point/box prompts), plus Markdown/HTML reports and a NiiVue 3D page. Renderers are pluggable.

Images never leave the machine.

Quick start

# 1. install (Python 3.10+)
pip install "open-med-mcp @ git+https://github.com/d0ng231/open-med-mcp"
#    optional local model backends (or use containers, see below):
pip install "open-med-mcp[sam2,totalsegmentator] @ git+https://github.com/d0ng231/open-med-mcp"   # pick extras: sam2,
#    totalsegmentator, lungmask, hdbet, nnunet, monai, torchxrayvision  -  or [models] for all

# 2. check the environment and fetch weights you want to use
open-med-mcp doctor
open-med-mcp models download medsam2

# 3. register the server with your agent (run inside the folder that holds your images)
claude mcp add open-med-mcp -e OMM_WORKSPACE=$PWD -- open-med-mcp serve      # Claude Code
codex mcp add open-med-mcp --env OMM_WORKSPACE=$PWD -- open-med-mcp serve    # Codex CLI
open-med-mcp client-config claude-desktop                                    # prints JSON for other clients

Then talk to your agent:

"Segment the liver in ct.nii.gz, check the result in three planes, and give me the volume."

A typical run looks like this (tool calls made by the agent):

get_conventions()                               -> coordinate + prompt conventions
inspect_image("ct.nii.gz")                      -> 512x512x210, 0.8x0.8x1.5 mm, CT, RAS, preview
get_guideline("segmentation-3d-ct")             -> protocol: TotalSegmentator first, MedSAM2 to refine
run_model("totalsegmentator", {"image": "ct.nii.gz"}, params={"roi_subset": ["liver"]})
render_view("ct.nii.gz", masks=[mask], layout="three-plane", window="soft-tissue")   -> PNG (agent looks)
mask_to_prompts(mask)                           -> box prompt for a promptable model
segment("ct.nii.gz", model="medsam2", prompts=[{"type": "box", "coords": [...], "slice": 97}])
compare_masks(ts_mask, medsam2_mask, image="ct.nii.gz")   -> Dice, HD95, volume difference
postprocess_mask(mask, ["largest_component", "fill_holes"])
mask_stats(mask, image="ct.nii.gz")            -> 1432 mL, mean 58 HU
write_report("Liver volumetry", sections=[...])

Related MCP server: MedVision MCP

Tools

group

tools

inspect

inspect_image (geometry, orientation, planes, statistics, modality guess, preview), list_workspace, list_dicom_series, convert_image

models

list_models, describe_model, download_weights, segment (promptable or automatic), run_model (any model/task), classify_image, detect, ask_vlm, run_batch (cohorts -> CSV), get_job / list_jobs (background runs)

clinical criteria

measure_lesion + recist_response (RECIST 1.1), fleischner_recommendation (2017), tirads_score (ACR TI-RADS), agatston_score (coronary calcium), cardiothoracic_ratio, future_liver_remnant, mayo_adpkd_class

masks

mask_stats (volumes, bboxes, components, intensities), postprocess_mask, compare_masks (Dice, IoU, HD95, ASSD), mask_to_prompts, combine_masks, mask_features (shape + first-order radiomics), mask_to_mesh (STL/OBJ)

processing

resample_image, reorient_image, crop_image, n4_bias_correction, register_images (rigid / affine / B-spline), apply_transform

viewer

render_view (PNG the agent sees), export_viewer (HTML for humans), write_report, list_renderers

guidance

list_guidelines, get_guideline, get_conventions (+ MCP prompts and resources), list_plugins

Full reference with every parameter: docs/tools.md. Coordinate conventions: docs/coordinates.md.

Models

model

what it does

modalities

prompts

how it runs

medsam2

MedSAM2: promptable 2D + 3D segmentation (slice propagation), medical fine-tune of SAM 2.1

CT, MR, PET, US, endoscopy

box, points

local [sam2], Docker, Apptainer

sam2

SAM 2.1 tiny / small / base+ / large

any

box, points

local [sam2], Docker, Apptainer

voxtell

VoxTell (CVPR 2026): free-text prompts ("liver", "left kidney", "liver tumor") -> 3D masks

CT, MR, PET

text

local [voxtell], Docker, Apptainer

totalsegmentator

117 CT structures, MR variant, vessels, body regions ...

CT, MR

-

local [totalsegmentator], Docker, Apptainer

lungmask

lungs (R231) and lobes (LTRCLobes) + LAA% emphysema index

CT

-

local [lungmask], Docker, Apptainer

hdbet

HD-BET 2.0 brain extraction (mask + stripped image)

MR

-

local [hdbet], Docker, Apptainer

synthstrip

FreeSurfer SynthStrip skull stripping, official image wrapped

MR, CT, PET

-

Docker, Apptainer (host mri_synthstrip if installed)

nnunet

any nnU-Net v2 model (results folder, exported zip, dataset name)

any

-

local [nnunet], Docker, Apptainer

monai

MONAI Model Zoo bundles: segmentation (spleen, pancreas, whole body, BraTS, prostate ...) and detection (lung nodules, RetinaNet)

CT, MR

-

local [monai], Docker, Apptainer

torchxrayvision

chest X-ray: 18-finding classification, 14-structure anatomy segmentation (-> cardiothoracic ratio), biological age

XR

-

local [torchxrayvision], Docker, Apptainer

vlm

vision-language: MedGemma 4B by default (any HF image-text-to-text model, e.g. Qwen2.5-VL) - describe, answer, draft

any

text

local [vlm], Docker, Apptainer

radiomics

pyradiomics: IBSI feature extraction (shape, first order, GLCM, GLRLM, GLSZM, GLDM, NGTDM, filters) per label

CT, MR, PET

-

local (Python 3.9 venv), Docker, Apptainer

classical

threshold / Otsu / multi-range / seeded region growing

any

seeds

local (no extras), Docker, Apptainer

open-med-mcp models list                              # what is available
open-med-mcp models check hdbet                       # which backend can run it here
open-med-mcp models pull medsam2                      # docker pull ghcr.io/d0ng231/open-med-mcp-sam2:0.1
open-med-mcp models pull synthstrip --engine apptainer   # HPC: official image -> .sif
open-med-mcp models build lungmask --engine apptainer    # or build from the Dockerfile (converted to a .def)
open-med-mcp run lungmask --image chest_ct.nii.gz --task lobes
open-med-mcp run medsam2 --image ct.nii.gz --prompts '[{"type":"box","coords":[60,80,20,140,170,20]}]'
open-med-mcp run voxtell --image ct.nii.gz --prompts '[{"type":"text","text":"liver"},{"type":"text","text":"spleen"}]'

Adding a model = copy src/open_med_mcp/zoo/_template/, edit the manifest, implement run.py against the job contract, add a Dockerfile. Wrapping an existing image (as synthstrip does) needs only a manifest with a command template. User models can live outside the package (OMM_MODEL_DIRS). See docs/models.md.

Guidelines

Workflow presets: getting-started, segmentation-3d-ct, segmentation-3d-mri, segmentation-2d-prompted, brain-mri-preprocessing, chest-xray-triage, chest-xray-anatomy-and-ctr, lung-ct-analysis, registration-followup, batch-processing, multi-organ-ct-report, compare-two-segmentations, qc-checklist.

Clinical criteria presets (each cites its source and states its scope): recist-1-1, fleischner-2017, lung-rads-2022, li-rads-2018, acr-ti-rads-2017, coronary-calcium-agatston, organ-volume-reference-ranges.

Add your own: put *.md files with YAML front matter into omm_guidelines/ in the workspace (or any directory in OMM_GUIDELINE_DIRS). A file with the same name overrides the preset. Guidelines are also exposed as MCP prompts (/mcp__open-med-mcp__segmentation-3d-ct in Claude Code) and as guideline://<name> resources. See docs/guidelines.md.

Viewer

  • render_view(...) - PNG figures for the agent, with native-voxel tick labels.

  • export_viewer(...) - one self-contained HTML file (no server, no CDN): cine/scroll through slices, toggle the overlay, invert, zoom/pan, and click or drag for a point/box prompt in native coordinates (with a millimetre size) that feeds back into segment.

  • open-med-mcp serve-viewer ct.nii.gz -m mask.nii.gz - 3D view (NiiVue) on localhost.

  • write_report(...) - Markdown + HTML with embedded figures.

  • Custom renderers: implement render(image, masks, spec) and register with @register_renderer. See docs/viewer.md.

automatic anatomy: run_model("totalsegmentator", ...)

free-text prompts: segment(ct, model="voxtell", prompts=[{"type": "text", "text": "liver"}, ...])

TotalSegmentator montage

VoxTell text prompts

skull stripping: run_model("hdbet", ...) vs synthstrip

chest X-ray: classify_image("cxr.png")

brain masks

CXR classification

2D promptable: segment("slice.png", model="medsam2", prompts=[box])

agent QC view: compare_masks(...)

2D MedSAM2

compare masks

chest X-ray anatomy + cardiothoracic_ratio(...)

classify + measure + criteria

CXR anatomy

RECIST measure_lesion/recist_response, Fleischner, TI-RADS, Agatston, ask_vlm (MedGemma), run_model("radiomics", ...)

All figures are real tool outputs on public sample data (abdominal CT, MNI152 template, NIH chest X-ray; see examples/get_sample_data.sh).

Plug in your own

Everything is extensible from the workspace, without forking:

open-med-mcp new plugin lesion-count     # omm_plugins/lesion_count.py: register(server) + your @server.tool()s
open-med-mcp new model my-unet           # omm_models/my-unet/: manifest + run.py + Dockerfile (job contract)
open-med-mcp new model synthseg --wrapped-image freesurfer/synthseg   # manifest only, drives the official image
open-med-mcp new guideline my-protocol   # omm_guidelines/my-protocol.md
open-med-mcp plugins list                # what loads, and why something did not

Plug-in tools use open_med_mcp.plugin_api (path resolution, cached image loading, previews, result packaging) and appear next to the built-in tools; packaged plug-ins register through the open_med_mcp.plugins entry point. See docs/plugins.md and examples/plugins/.

Running reliably in any MCP client

  • stdio hygiene - the server never writes to stdout; logs go to stderr and $OMM_HOME/logs/server.log.

  • Long runs - model tools stream MCP progress notifications; pass wait=false to get a job id immediately and poll get_job (results, previews and logs are also on disk under omm_outputs/).

  • Concurrency - tools run in worker threads; rendering, caches and provenance are lock-protected.

  • Payload limits - inline previews are capped (OMM_MAX_IMAGE_BYTES, default 1.5 MB) and can be switched off for text-only clients (OMM_RETURN_IMAGES=0); every result also names the saved file.

  • Transports - open-med-mcp serve (stdio), --transport streamable-http / sse for remote agents; over HTTP file access is confined to the workspace by default.

  • Errors - every tool returns a readable is_error result instead of crashing the session.

  • Schemas - every parameter is typed and described; the test-suite validates all tool schemas.

Configuration

variable

default

meaning

OMM_WORKSPACE

current directory

root for relative paths; outputs go to <workspace>/omm_outputs/

OMM_HOME

~/.cache/open-med-mcp

weights and Apptainer images

OMM_RUNNER

auto

local / docker / apptainer; auto = local if importable, else docker, else apptainer

OMM_DEVICE

auto

cpu, cuda, cuda:1

OMM_ZOO_<ADAPTER>_PYTHON

current interpreter

interpreter of a dedicated venv for a local adapter (e.g. OMM_ZOO_SAM2_PYTHON)

OMM_MODEL_DIRS, OMM_GUIDELINE_DIRS

-

extra adapters / guidelines (:-separated)

OMM_IMAGE_PREFIX

ghcr.io/d0ng231/open-med-mcp

registry prefix for container images

OMM_ALLOW_OUTSIDE_WORKSPACE

true (stdio) / false (HTTP)

confine file access to the workspace

OMM_PLUGIN_DIRS

-

extra plug-in directories (:-separated)

OMM_RETURN_IMAGES

true

inline preview images in results

OMM_MAX_IMAGE_BYTES

1500000

cap for one inline image

OMM_LOG_LEVEL, OMM_LOG_FILE

INFO, $OMM_HOME/logs/server.log

logging

OMM_CACHE_MB

1500

in-memory image cache budget

HPC / SLURM

No Docker on the cluster? open-med-mcp models pull <model> --engine apptainer fetches the GHCR image as a .sif, or models build --engine apptainer converts the Dockerfile to an Apptainer definition and builds it. Set OMM_RUNNER=apptainer; GPU passthrough (--nv) is automatic when a GPU is visible. Alternatively point OMM_ZOO_SAM2_PYTHON at a venv with PyTorch and run models on a GPU node with the local backend. See docs/hpc.md.

Documentation

Development

git clone https://github.com/d0ng231/open-med-mcp && cd open-med-mcp
uv venv && uv pip install -e ".[dev]"
.venv/bin/ruff check src tests && .venv/bin/python -m pytest -q      # CPU-only tests, ~1 min

The test-suite covers the whole stack (I/O, coordinates, processing, viewer, job contract, MCP server, CLI) with synthetic data; the real models are verified on GPU/CPU before a release.

Acknowledgements

Model weights are downloaded from the upstream projects and remain subject to their licenses.

Disclaimer

open-med-mcp is research software. It is not a medical device and must not be used for clinical decision making. Outputs are model predictions that need expert review.

License

Apache-2.0. See LICENSE. If you use it in research, please cite via CITATION.cff.

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Provides AI-powered medical image analysis tools for LLM agents, enabling tasks such as X-ray classification, interactive segmentation, and visual question answering. It supports multi-step diagnostic reasoning and clinical workflows through a suite of specialized medical AI models.
    MIT
  • A
    license
    Not graded
    quality
    A
    maintenance
    Enables AI agents to control a local CBCT viewer for dental and maxillofacial scans, with navigation verbs like open scan, set window, navigate slices, and snapshot, without executing code or returning interpretations.
    5
    AGPL 3.0