Skip to main content
Glama

MCP-сервер NiChart DLMUSE

Размещает cbica/nichart_dlmuse (T1 MRI skull-strip + MUSE ROI сегментация) за MCP-сервером на GPU-инстансе EC2, чтобы Claude Code мог запускать сегментацию удалённо, а не каждому пользователю требовался локальный GPU.

Почему это устроено именно так

Аргументы инструментов MCP — это JSON. Файл .nii.gz весит десятки мегабайт бинарных данных, а сегментация занимает ~1-2 минуты на GPU — это слишком медленно и слишком много для одного блокирующего вызова инструмента. Поэтому:

  • Передача файлов происходит вне протокола MCP — через обычную аутентифицированную конечную точку POST /upload. Через аргумент инструмента MCP передаётся только небольшой upload_id.

  • Задачи асинхронны: run_dlmuse_segmentation ставит задачу в очередь и сразу возвращается; get_job_status опрашивает статус; get_job_result получает CSV прямо в ответе, а также ссылки для скачивания файлов масок.

  • Один воркер, сериализация: это один общий GPU, поэтому одновременно выполняется только один docker run, ожидающий в очереди за asyncio.Queue.

  • Bearer-токен аутентификации для каждого члена команды на каждой конечной точке, кроме /healthz.

  • Приватный инстанс, без публичного веб-уровня: приложение привязывается только к 127.0.0.1, а security group открывает только SSH (22). Пользователи подключаются через SSH-проброс порта со своего ноутбука на этот loopback-порт с помощью своего приватного ключа — нет ни домена, ни чего-либо доступного из интернета для атаки.

  • TLS — это самоподписанный сертификат, сгенерированный один раз на инстансе, поскольку публично выпущенный сертификат (Let's Encrypt и т.п.) требует доступности инстанса из интернета для проверки домена, а этот инстанс недоступен. Каждый пользователь доверяет этому сертификату на своём ноутбуке (см. ниже).

  • Сканы не хранятся вечно: загруженные файлы и результаты задач удаляются через RETENTION_HOURS (по умолчанию 24 часа).

Архитектура

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

Структура репозитория

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)

Развёртывание на EC2 (однократно)

Требуется существующий GPU-инстанс EC2 (рекомендуется AWS Deep Learning AMI — драйвер NVIDIA и Docker обычно уже установлены).

  1. Скопируйте этот репозиторий на инстанс (git clone / scp -r).

  2. cp .env.example .env и заполните как минимум TOKENS — пары name:token для каждого члена команды, разделённые запятыми. Сгенерируйте токены с помощью openssl rand -hex 32.

  3. В security group инстанса разрешите только входящий 22 (SSH), ограничив его IP-адресами вашей команды или bastion-хостом. Больше ничего не открывайте — ни 443, ни 8420. Приложение привязывается к 127.0.0.1 и доступно только через SSH-туннель.

  4. Запустите скрипт подготовки:

    sudo ./deploy/setup_ec2.sh

    Он идемпотентен — устанавливает Docker/nvidia-container-toolkit только при отсутствии, загружает образ DLMUSE, создаёт отдельного служебного пользователя nichart-mcp, разворачивает код в /opt/nichart-mcp, генерирует самоподписанный TLS-сертификат (SAN = 127.0.0.1/localhost) и устанавливает systemd-сервис nichart-mcp.

  5. Проверьте, находясь на самом инстансе:

    curl --cacert /opt/nichart-mcp/tls/server.crt https://127.0.0.1:8420/healthz
  6. Скопируйте /opt/nichart-mcp/tls/server.crt с инстанса, чтобы передать его каждому члену команды (например, scp -i key.pem ec2-user@<instance-ip>:/opt/nichart-mcp/tls/server.crt .).

Чтобы позже добавить или отозвать пользователя: отредактируйте TOKENS в /opt/nichart-mcp/.env на инстансе, затем выполните sudo systemctl restart nichart-mcp.

Обновление кода

Повторно запустите sudo ./deploy/setup_ec2.sh из обновлённой копии на инстансе — он повторно синхронизирует /opt/nichart-mcp (не трогая существующий TLS-сертификат), переустанавливает зависимости и перезапускает сервис.

Подключение с ноутбука

Каждому члену команды понадобятся: его SSH-приватный ключ (для Windows PuTTY-ключа .ppk один раз преобразуйте его с помощью puttygen key.ppk -O private-openssh -o key.pem, чтобы стандартный клиент ssh мог его использовать), его bearer-токен и файл server.crt из шага 6 настройки.

1. Доверьтесь самоподписанному сертификату один раз, чтобы curl/Claude Code перестали его отклонять:

  • 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. Откройте SSH-туннель (не закрывайте его в терминале, пока используете Claude Code):

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

Если у инстанса нет публичного IP-адреса и вы подключаетесь только через bastion-хост, добавьте -J <bastion_user>@<bastion_host>.

3. Зарегистрируйте MCP-сервер в Claude Code один раз:

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

Использование

При открытом туннеле попросите Claude Code сегментировать скан; он сделает следующее:

  1. Загрузит файл (через туннель, так что 127.0.0.1:8420 корректен, даже если файл предназначен удалённому инстансу):

    curl -X POST -H "Authorization: Bearer <token>" \
      -F "file=@/path/to/scan.nii.gz" \
      https://127.0.0.1:8420/upload
    # -> {"upload_id": "..."}
  2. Вызовет инструмент run_dlmuse_segmentation с этим upload_id -> получит job_id.

  3. Будет опрашивать get_job_status(job_id), пока status == "done" (обычно ~1-2 минуты на GPU).

  4. Вызовет get_job_result(job_id) -> CSV с объёмами ROI прямо в ответе, плюс ссылки на /download/{job_id}/{filename} для NIfTI-файлов масок ICV и MUSE (загрузите их с https://127.0.0.1:8420/download/..., используя тот же bearer-токен и тот же туннель).

Эксплуатационные заметки

  • Конкуренция за GPU: одновременно выполняется только одна задача по замыслу (один общий GPU). При активной работе команда увидит очередь задач; get_job_status сообщает queue_position.

  • Состояние задач хранится в памяти: systemctl restart nichart-mcp приводит к потере записей о выполняющихся задачах (загруженный скан и частичные результаты на диске не затрагиваются, но задачу придётся отправить заново). Для небольшой команды это нормально; если этого станет недостаточно, замените in-memory dict в server/jobs.py на Redis/RQ.

  • PHI: сканы — это реальные данные пациентов. RETENTION_HOURS ограничивает время их хранения на диске, но убедитесь, что это соответствует вашим требованиям к обработке данных, прежде чем использовать систему на реальных пациентах. Рассмотрите возможность включения шифрования EBS на томе инстанса, если вы ещё этого не сделали.

  • Контейнер DLMUSE работает под root внутри (он жёстко прописывает запись в /app/pipeline.log, поэтому не может работать с --user). Его результаты принадлежат root; очистка в server/jobs.py использует одноразовый контейнер alpine, чтобы принудительно удалить эти каталоги.

Локальная разработка

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

Это запускает полный сервер (аутентификация, загрузка, очередь задач, MCP-инструменты) локально. Для фактического выполнения сегментации всё равно требуется Docker с доступом к GPU — на машине без GPU задачи будут падать на шаге docker run, но всё остальное (маршрутизация, аутентификация, очередь, отчёты о статусе/ошибках) можно проверить.

-
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