Skip to main content
Glama

NiChart DLMUSE MCP server

Hosts cbica/nichart_dlmuse (T1 MRI extracción de cráneo + segmentación de ROI con MUSE) detrás de un servidor MCP en una instancia EC2 con GPU, para que Claude Code pueda ejecutar segmentaciones de forma remota en lugar de que cada usuario necesite una GPU local.

Por qué tiene esta forma

Los argumentos de las herramientas MCP son JSON. Un .nii.gz son decenas de MB de datos binarios, y la segmentación tarda ~1-2 minutos en GPU — demasiado lenta y demasiado grande para una única llamada de herramienta bloqueante. Por lo tanto:

  • La transferencia de archivos ocurre fuera del protocolo MCP, a través de un endpoint POST /upload con autenticación simple. Solo un pequeño upload_id fluye a través de un argumento de herramienta MCP.

  • Los trabajos son asíncronos: run_dlmuse_segmentation encola y devuelve inmediatamente; get_job_status sondea; get_job_result obtiene el CSV directamente, además de los enlaces de descarga de los archivos de máscara.

  • Un solo trabajador, serializado: es una GPU compartida, así que solo un docker run se ejecuta a la vez, en cola detrás de un asyncio.Queue.

  • Autenticación con token Bearer para cada miembro del equipo en cada endpoint excepto /healthz.

  • Instancia privada, sin capa web pública: la aplicación se vincula solo a 127.0.0.1, y el grupo de seguridad no abre nada más que SSH (22). Los usuarios acceden a ella mediante el reenvío de puertos SSH desde su portátil a ese puerto de loopback con su clave privada — no hay dominio ni nada expuesto a internet que atacar.

  • TLS es un certificado autofirmado, generado una vez en la instancia, ya que un certificado emitido públicamente (Let's Encrypt, etc.) requiere que la instancia sea accesible desde internet para la validación de dominio, cosa que esta no es. Cada usuario confía en ese certificado en su portátil (ver más abajo).

  • Los escaneos no duran para siempre: las subidas y las salidas de los trabajos se eliminan después de RETENTION_HOURS (por defecto 24 h).

Arquitectura

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

Estructura del repositorio

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)

Configuración única de EC2

Requiere una instancia EC2 con GPU existente (se recomienda AWS Deep Learning AMI — el controlador NVIDIA y Docker suelen estar ya instalados).

  1. Copia este repositorio a la instancia (git clone / scp -r).

  2. cp .env.example .env y rellena al menos TOKENS — un par name:token por miembro del equipo, separados por comas. Genera los tokens con openssl rand -hex 32.

  3. En el grupo de seguridad de la instancia: permite solo el tráfico entrante 22 (SSH), restringido a las IPs de tu equipo o a un bastión. No abras nada más — ni 443, ni 8420. La aplicación se vincula a 127.0.0.1 y solo es accesible a través de un túnel SSH.

  4. Ejecuta el script de aprovisionamiento:

    sudo ./deploy/setup_ec2.sh

    Es idempotente — instala Docker/nvidia-container-toolkit solo si faltan, descarga la imagen DLMUSE, crea un usuario de servicio dedicado nichart-mcp, despliega el código en /opt/nichart-mcp, genera un certificado TLS autofirmado (SAN = 127.0.0.1/localhost) e instala el servicio systemd nichart-mcp.

  5. Verifica, desde la propia instancia:

    curl --cacert /opt/nichart-mcp/tls/server.crt https://127.0.0.1:8420/healthz
  6. Copia /opt/nichart-mcp/tls/server.crt fuera de la instancia para poder entregárselo a cada miembro del equipo (p. ej. scp -i key.pem ec2-user@<instance-ip>:/opt/nichart-mcp/tls/server.crt .).

Para añadir o revocar un usuario más tarde: edita TOKENS en /opt/nichart-mcp/.env en la instancia y luego ejecuta sudo systemctl restart nichart-mcp.

Actualización del código

Vuelve a ejecutar sudo ./deploy/setup_ec2.sh desde un checkout actualizado en la instancia — resincroniza /opt/nichart-mcp (dejando el certificado TLS existente intacto), reinstala las dependencias y reinicia el servicio.

Conexión desde un portátil

Cada miembro del equipo necesita: su clave privada SSH (para una clave .ppk de PuTTY en Windows, conviértela una vez con puttygen key.ppk -O private-openssh -o key.pem para que el cliente ssh estándar pueda usarla), su token Bearer y el archivo server.crt del paso 6 de la configuración.

1. Confía en el certificado autofirmado una vez, para que curl/Claude Code dejen de rechazarlo:

  • 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. Abre el túnel SSH (déjalo corriendo en una terminal mientras uses Claude Code):

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

Si la instancia no tiene IP pública y solo llegas a ella a través de un bastión, añade -J <bastion_user>@<bastion_host>.

3. Registra el servidor MCP con Claude Code, una sola vez:

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

Uso

Con el túnel abierto, pide a Claude Code que segmente un escaneo; este hará lo siguiente:

  1. Subir el archivo (a través del túnel, por lo que 127.0.0.1:8420 es correcto aunque el archivo vaya dirigido a la instancia remota):

    curl -X POST -H "Authorization: Bearer <token>" \
      -F "file=@/path/to/scan.nii.gz" \
      https://127.0.0.1:8420/upload
    # -> {"upload_id": "..."}
  2. Llamar a la herramienta run_dlmuse_segmentation con ese upload_id -> obtener un job_id.

  3. Sondear get_job_status(job_id) hasta que status == "done" (normalmente ~1-2 min en GPU).

  4. Llamar a get_job_result(job_id) -> CSV de volúmenes ROI incluido directamente, además de enlaces /download/{job_id}/{filename} para los archivos NIfTI de máscara ICV y MUSE (obtener esos desde https://127.0.0.1:8420/download/... con el mismo token Bearer, a través del mismo túnel).

Notas de operación

  • Concurrencia de GPU: un trabajo se ejecuta a la vez por diseño (una única GPU compartida). Un equipo ocupado verá trabajos en cola; get_job_status informa de queue_position.

  • El estado del trabajo está en memoria: un systemctl restart nichart-mcp pierde los registros de trabajos en curso (el escaneo subido y cualquier salida parcial en disco no se ven afectados, pero tendrías que volver a enviarlo). Está bien a la escala de un equipo pequeño; si lo superas, cambia el diccionario en memoria en server/jobs.py por Redis/RQ.

  • PHI: los escaneos son datos reales de pacientes. RETENTION_HOURS limita cuánto tiempo permanecen en disco, pero confirma que eso es compatible con tus requisitos de manejo de datos antes de usarlo con pacientes reales. Considera habilitar el cifrado EBS en el volumen de la instancia si aún no lo has hecho.

  • El contenedor DLMUSE se ejecuta como root en su interior (escribe de forma fija en /app/pipeline.log, por lo que no puede ejecutarse con --user). Su salida termina siendo propiedad de root; la limpieza de server/jobs.py recurre a un contenedor alpine desechable para forzar la eliminación de esos directorios.

Desarrollo local

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

Esto ejecuta el servidor completo (autenticación, subida, cola de trabajos, herramientas MCP) localmente. Ejecutar realmente una segmentación todavía requiere Docker con acceso a GPU — en una máquina sin GPU, los trabajos fallarán en el paso docker run, pero todo lo demás (enrutamiento, autenticación, colas, informes de estado/error) se puede probar.

-
license - not tested
-
quality - not tested
-
maintenance - not tested

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

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

Related MCP Connectors

  • Remote MCP server for RunComfy Serverless API (ComfyUI): deployments and async inference.

  • Cloud-hosted MCP server for durable AI memory

  • Hosted MCP server connecting claude.ai, ChatGPT and other AI apps to your own computer

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/euroso97/DLMUSE_MCP'

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