Skip to main content
Glama

NiChart DLMUSE MCP server

Hostet cbica/nichart_dlmuse (T1-MRT-Skull-Strip + MUSE-ROI-Segmentierung) hinter einem MCP-Server auf einer GPU-EC2-Instanz, damit Claude Code Segmentierungen remote ausführen kann, anstatt dass jeder Benutzer eine lokale GPU benötigt.

Warum es so aufgebaut ist

MCP-Werkzeugargumente sind JSON. Eine .nii.gz enthält Dutzende MB Binärdaten, und die Segmentierung dauert auf der GPU ~1-2 Minuten – zu langsam und zu groß für einen einzelnen blockierenden Werkzeugaufruf. Also:

  • Der Dateitransfer erfolgt außerhalb des MCP-Protokolls, über einen einfachen authentifizierten POST /upload-Endpunkt. Nur eine kleine upload_id fließt jemals durch ein MCP-Werkzeugargument.

  • Jobs sind asynchron: run_dlmuse_segmentation reiht ein und kehrt sofort zurück; get_job_status pollt; get_job_result holt die CSV inline sowie Download-Links für die Maskendateien.

  • Ein Worker, serialisiert: Es gibt eine gemeinsame GPU, daher wird jeweils nur ein docker run ausgeführt, das in einer asyncio.Queue eingereiht ist.

  • Bearer-Token-Authentifizierung pro Teammitglied auf jedem Endpunkt außer /healthz.

  • Private Instanz, keine öffentliche Webschicht: Die App bindet nur an 127.0.0.1, und die Sicherheitsgruppe öffnet nur SSH (22). Benutzer erreichen sie per SSH-Portweiterleitung von ihrem Laptop in diesen Loopback-Port mit ihrem privaten Schlüssel – es gibt keine Domain und nichts Internetzugewandtes, das angegriffen werden könnte.

  • TLS ist ein selbstsigniertes Zertifikat, das einmal auf der Instanz erzeugt wird, da ein öffentlich ausgestelltes Zertifikat (Let's Encrypt usw.) erfordert, dass die Instanz für die Domain-Validierung aus dem Internet erreichbar ist, was hier nicht der Fall ist. Jeder Benutzer vertraut diesem einen Zertifikat auf seinem Laptop (siehe unten).

  • Scans leben nicht ewig: Uploads und Job-Ausgaben werden nach RETENTION_HOURS (Standard 24h) gelöscht.

Related MCP server: agent-bridge-mcp

Architektur

Claude Code (laptop)                    SSH tunnel                  EC2 (private, SG: 22 only)
  │  ssh -i key.pem -L 8420:127.0.0.1:8420 user@instance ─────────────────►  │
  │                                                                          │
  │  1. curl https://127.0.0.1:8420/upload ─────(via tunnel)──────────►  MCP server :8420 (127.0.0.1, self-signed TLS)
  │  2. run_dlmuse_segmentation ────────────────(via tunnel)──────────►         │
  │  3. get_job_status (poll) ──────────────────(via tunnel)──────────►  asyncio job queue (1 worker)
  │  4. get_job_result ─────────────────────────(via tunnel)──────────►         │
                                                                   docker run --gpus all cbica/nichart_dlmuse

Repo-Struktur

server/app.py     MCP tools (run_dlmuse_segmentation, get_job_status, get_job_result)
                  + HTTP routes (/upload, /download/{job_id}/{filename}, /healthz)
server/jobs.py    job queue/worker, docker invocation, root-owned-output cleanup
server/auth.py    bearer-token ASGI middleware
server/config.py  env-driven settings
deploy/           EC2 provisioning script (installs Docker, GPU toolkit, self-signed cert, systemd unit)

Einmalige EC2-Einrichtung

Erfordert eine vorhandene GPU-EC2-Instanz (AWS Deep Learning AMI empfohlen – NVIDIA-Treiber und Docker sind normalerweise bereits installiert).

  1. Kopieren Sie dieses Repo auf die Instanz (git clone / scp -r).

  2. cp .env.example .env und füllen Sie mindestens TOKENS aus – ein name:token-Paar pro Teammitglied, durch Kommas getrennt. Generieren Sie Token mit openssl rand -hex 32.

  3. In der Sicherheitsgruppe der Instanz: Erlauben Sie nur eingehendes 22 (SSH), beschränkt auf die IPs Ihres Teams oder einen Bastion-Host. Öffnen Sie nichts anderes – kein 443, kein 8420. Die App bindet an 127.0.0.1 und ist nur über einen SSH-Tunnel erreichbar.

  4. Führen Sie das Provisionierungsskript aus:

    sudo ./deploy/setup_ec2.sh

Es ist idempotent – installiert Docker/nvidia-container-toolkit nur, wenn es fehlt, zieht das DLMUSE-Image, erstellt einen dedizierten Dienstbenutzer nichart-mcp, stellt den Code unter /opt/nichart-mcp bereit, generiert ein selbstsigniertes TLS-Zertifikat (SAN = 127.0.0.1/localhost) und installiert den nichart-mcp-systemd-Dienst. 5. Überprüfen Sie von der Instanz selbst:

GXP4 6. Kopieren Sie /opt/nichart-mcp/tls/server.crt von der Instanz, um es jedem Teammitglied zu übergeben (z. B. scp -i key.pem ec2-user@<instance-ip>:/opt/nichart-mcp/tls/server.crt .).

Um später einen Benutzer hinzuzufügen oder zu entfernen: Bearbeiten Sie TOKENS in /opt/nichart-mcp/.env auf der Instanz und führen Sie dann sudo systemctl restart nichart-mcp aus.

Aktualisieren des Codes

Führen Sie sudo ./deploy/setup_ec2.sh von einem aktualisierten Checkout auf der Instanz erneut aus – es synchronisiert /opt/nichart-mcp erneut (das vorhandene TLS-Zertifikat bleibt unangetastet), installiert Abhängigkeiten neu und startet den Dienst neu.

Verbinden von einem Laptop

Jedes Teammitglied benötigt: seinen SSH-privaten Schlüssel (für einen Windows-PuTTY-.ppk-Schlüssel einmal mit puttygen key.ppk -O private-openssh -o key.pem konvertieren, damit der Standard-ssh-Client ihn verwenden kann), sein Bearer-Token und die server.crt-Datei aus Einrichtungsschritt 6.

1. Vertrauen Sie dem selbstsignierten Zertifikat einmal, damit curl/Claude Code es nicht mehr ablehnen:

  • macOS: security add-trusted-cert -d -r trustRoot -k ~/Library/Keychains/login.keychain-db server.crt

  • Linux: sudo cp server.crt /usr/local/share/ca-certificates/nichart-mcp.crt && sudo update-ca-certificates

  • Windows: certutil -addstore -f "ROOT" server.crt

2. Öffnen Sie den SSH-Tunnel (lassen Sie ihn in einem Terminal laufen, während Sie Claude Code verwenden):

ssh -i key.pem -N -L 8420:127.0.0.1:8420 <ssh_user>@<instance-ip>

Wenn die Instanz keine öffentliche IP hat und Sie sie nur über einen Bastion-Host erreichen, fügen Sie -J <bastion_user>@<bastion_host> hinzu.

3. Registrieren Sie den MCP-Server bei Claude Code, einmalig:

claude mcp add --transport http nichart-dlmuse https://127.0.0.1:8420/mcp \
  --header "Authorization: Bearer <their-token>"

Verwendung

Wenn der Tunnel geöffnet ist, bitten Sie Claude Code, einen Scan zu segmentieren; es wird Folgendes tun:

  1. Laden Sie die Datei hoch (durch den Tunnel, sodass 127.0.0.1:8420 korrekt ist, auch wenn die Datei für die entfernte Instanz bestimmt ist):

    curl -X POST -H "Authorization: Bearer <token>" \
      -F "file=@/path/to/scan.nii.gz" \
      https://127.0.0.1:8420/upload
    # -> {"upload_id": "..."}
  2. Rufen Sie das run_dlmuse_segmentation-Werkzeug mit dieser upload_id auf -> erhalten Sie eine job_id.

  3. Rufen Sie get_job_status(job_id) wiederholt auf, bis status == "done" ist (normalerweise ~1-2 Min. auf der GPU).

  4. Rufen Sie get_job_result(job_id) auf -> ROI-Volumina-CSV inline, plus /download/{job_id}/{filename}-Links für die ICV- und MUSE-Masken-NIfTI-Dateien (rufen Sie diese von https://127.0.0.1:8420/download/... mit demselben Bearer-Token durch denselben Tunnel ab).

Betriebshinweise

  • GPU-Nebenläufigkeit: Es läuft absichtlich jeweils ein Job (eine gemeinsame GPU). Ein ausgelastetes Team sieht, wie sich Jobs in die Warteschlange einreihen; get_job_status meldet queue_position.

  • Der Jobstatus liegt im Speicher: Ein systemctl restart nichart-mcp verliert laufende Jobdatensätze (der hochgeladene Scan und etwaige Teilergebnisse auf der Platte sind nicht betroffen, aber Sie müssten erneut einreichen). Für kleine Teams in Ordnung; falls Sie darüber hinauswachsen, tauschen Sie das In-Memory-Dict in server/jobs.py gegen Redis/RQ.

  • PHI: Scans sind echte Patientendaten. RETENTION_HOURS begrenzt, wie lange sie auf der Platte liegen, aber bestätigen Sie, dass das mit Ihren Datenverarbeitungsanforderungen kompatibel ist, bevor Sie das auf echte Patienten anwenden. Erwägen Sie, die EBS-Verschlüsselung auf dem Volume der Instanz zu aktivieren, falls Sie das nicht bereits getan haben.

  • Der DLMUSE-Container läuft im Inneren als root (er schreibt fest verdrahtet nach /app/pipeline.log, daher kann er nicht unter --user laufen). Seine Ausgaben gehören am Ende root; die Bereinigung in server/jobs.py greift auf einen Wegwerf-alpine-Container zurück, um diese Verzeichnisse zwangsweise zu entfernen.

Lokale Entwicklung

python3 -m venv .venv && .venv/bin/pip install -r requirements.txt
cp .env.example .env   # fill in TOKENS
TOKENS=dev:devtoken DATA_DIR=/tmp/nichart-dev .venv/bin/python -m server.app

Dies führt den vollständigen Server (Authentifizierung, Upload, Job-Warteschlange, MCP-Werkzeuge) lokal aus. Eine Segmentierung tatsächlich auszuführen erfordert weiterhin Docker mit GPU-Zugriff – auf einem Rechner ohne GPU schlagen Jobs im docker run-Schritt fehl, aber alles andere (Routing, Authentifizierung, Warteschlangen, Status-/Fehlerberichterstattung) ist testbar.

Related MCP Connectors

Related MCP Servers