Skip to main content
Glama

fhirHydrant: FHIR MCP Server

Современный, полностью настраиваемый MCP-сервер с открытым исходным кодом на Node.js для FHIR API R4+. Он подключает MCP-совместимые клиенты к клиническим данным через SMART on FHIR v2 Backend Services, используя подписанные JWT-учётные данные клиента.

fhirHydrant превращает FHIR-ресурсы, именованные операции, терминологические запросы и пагинацию в MCP-инструменты. Ресурсы и операции по умолчанию — это отправные точки: ресурсы, операции, элементы управления поиском, инструкции и сообщения могут быть расширены, сокращены или заменены через файлы конфигурации без изменения исходного кода.

  • Аутентификация SMART Backend Services с размещением JWKS, ротацией ключей, обновлением токенов и динамическими областями действия

  • Настраиваемые инструменты ресурсов для поиска, прямого чтения, vread, истории и необязательного CRUD, управляемого метаданными

  • Управляемые конфигурацией именованные операции для клинических данных, терминологии, IPS, сопоставления пациентов, валидации и пользовательских рабочих процессов

  • Инструменты с учётом CapabilityStatement, элементы управления поиском, гейтинг операций и проверка областей действия во время выполнения

  • Функции экономии токенов: компактные ответы, фильтрация FHIRPath, лимиты байтов, формирование _count и повторная попытка при превышении размера Bundle

  • Необязательные терминологические инструменты, события аудита с минимальным PHI (без содержимого ресурсов по умолчанию) и транспорт stdio или Streamable HTTP

Примечание: Данные FHIR, возвращаемые через вызовы MCP-инструментов, могут содержать PHI. Убедитесь, что хранение транскриптов и поведение журналирования вашего MCP-клиента соответствуют вашим требованиям соответствия.

Содержание

Related MCP server: smart-mcp-server

Быстрый старт

Требования

  • Node.js >= 24

  • Поддерживаемый FHIR-сервер

  • Для SMART-аутентификации (по умолчанию): регистрация клиента SMART Backend Services и закрытый ключ RSA-2048 или EC P-384, чей открытый ключ доступен через JWKS

Для работы с публичным, неаутентифицированным тестовым FHIR-сервером установите FHIR_AUTH=none и полностью пропустите клиент и ключ (см. Неаутентифицированный доступ).

Транспорт stdio обычно требует внешне размещённый URL JWKS. Встроенная конечная точка /jwks доступна только когда fhirHydrant работает через HTTP с SMART-аутентификацией.

Установка

# install globally
npm install -g fhirhydrant

# or run without installing
npx fhirhydrant

Запуск из исходного кода:

git clone https://github.com/faulkj/fhirhydrant.git
cd fhirhydrant
npm install
npm run build

Конфигурация MCP-клиента

Для настольных MCP-клиентов stdio обычно является самым простым транспортом:

{
   "mcpServers": {
      "fhirhydrant": {
         "command": "npx",
         "args": ["-y", "fhirhydrant"],
         "env": {
            "MCP_TRANSPORT": "stdio",
            "FHIR_BASE_URL": "https://fhir.example.org",
            "FHIR_CLIENT_ID": "your-client-id",
            "FHIR_ACTIVE_KEY": "LS0tLS1CRUdJTi...base64-of-your-pem...",
            "FHIR_JWKS_URL": "https://example.org/.well-known/jwks.json"
         }
      }
   }
}

FHIR_ACTIVE_KEY — это ваш закрытый ключ PKCS#8 (RSA или EC P-384), закодированный в base64. kid автоматически вычисляется при запуске через усечённый отпечаток JWK и записывается в консоль.

Неаутентифицированный доступ

Чтобы указать fhirHydrant на публичную, неаутентифицированную конечную точку FHIR (удобно для тестирования на открытых песочницах), установите FHIR_AUTH=none. Никакой идентификатор клиента или подписывающий ключ не требуется, токен не запрашивается, и запросы отправляются без заголовка Authorization:

{
   "mcpServers": {
      "fhirhydrant": {
         "command": "npx",
         "args": ["-y", "fhirhydrant"],
         "env": {
            "MCP_TRANSPORT": "stdio",
            "FHIR_AUTH": "none",
            "FHIR_SERVER_URL": "https://hapi.fhir.org/baseR4"
         }
      }
   }
}

Инструменты

fhirHydrant регистрирует инструменты на основе конфигурации и проверок возможностей во время выполнения. Точный список зависит от папки config/resources/, предоставленных областей действия SMART, /metadata, настроек записи, настроек операций и настроек терминологии.

Инструмент или семейство

Доступен, когда

Назначение

Инструменты ресурсов

Ресурс настроен и разрешён метаданными/областями действия

Поиск, прямое чтение, vread, история и, опционально, CRUD FHIR-ресурсов

system_history

Сервер рекламирует системное взаимодействие history, и области действия позволяют

Получение истории изменений на уровне системы для всех типов ресурсов

capabilities

Всегда зарегистрирован

Просмотр сводки CapabilityStatement, зарегистрированных инструментов, пропущенных инструментов, параметров поиска, операций и примечаний к метаданным

paginate

Всегда зарегистрирован

Получение следующей страницы FHIR Bundle с использованием возвращённого сервером URL next

operate

Хотя бы одна именованная операция проходит гейтинг

Вызов настроенных именованных операций FHIR для клинических данных, терминологии, IPS, сопоставления, валидации или пользовательских рабочих процессов

bundle

Установлен FHIR_BUNDLE_CAPABILITIES

Отправка FHIR batch или transaction Bundle; записи требуют дополнительного согласия

terminology_lookup

Установлен FHIR_TERMINOLOGY_BASE_URL

Поиск одного кода LOINC или SNOMED CT

code_search

Установлен FHIR_TERMINOLOGY_BASE_URL

Поиск кодов LOINC или SNOMED CT по тексту

Инструменты ресурсов

Инструменты ресурсов генерируются из папки config/resources/ — по одному JSON-файлу на ресурс (например, patient.json), сканируемой при запуске. Поставляемая конфигурация охватывает распространённые клинические, административные, лекарственные, ресурсы практикующих врачей, организаций и документов. Добавьте файл, чтобы добавить ресурс, или удалите его, чтобы убрать — без изменения исходного кода.

Каждый инструмент ресурса поддерживает настроенные параметры поиска, необязательные прямые чтения с _id, fhirpath и, если не заблокирован компактный режим, responseMode. Прямое чтение происходит только когда _id является единственным непустым аргументом; _id вместе с другими параметрами остаётся поиском, чтобы намерение вызывающего не было молча отброшено.

Инструменты ресурсов по умолчанию выполняют поиск/чтение. Установите FHIR_WRITE_CAPABILITIES, чтобы включить действия CRUD, управляемые метаданными:

FHIR_WRITE_CAPABILITIES=create,update,patch,delete

Действие

Обязательные параметры

Вызов FHIR

vread

_id, _vid

GET /ResourceType/{id}/_history/{vid}

history

_id (экземпляр) или нет (тип)

GET /ResourceType/{id}/_history или GET /ResourceType/_history

create

body

POST /ResourceType

update

_id, body

PUT /ResourceType/{id}

patch

_id, body

PATCH /ResourceType/{id} с JSON Patch

delete

_id

DELETE /ResourceType/{id}

vread доступен, когда ресурс имеет supportsDirectRead и сервер рекламирует взаимодействие vread. history доступен, когда сервер рекламирует history-instance или history-type. Оба требуют разрешения SMART r. Необязательные параметры _since и _at фильтруют результаты истории. Ответы истории — это Bundles и поддерживают компактный режим, FHIRPath и объединение.

Тела записей проверяются перед вызовом FHIR: body.resourceType должен соответствовать ресурсу инструмента, body.id должен соответствовать _id для update, если он присутствует, а patch требует массив JSON Patch. Области действия выводятся из включённых возможностей: чтение/поиск использует system/Patient.rs, создание/чтение/поиск использует system/Patient.crs, а полная поддержка записи использует system/Patient.cruds. В SMART v2 нет отдельной буквы для patch, поэтому patch сопоставляется с u.

Основные инструменты

capabilities возвращает кэшированную сводку CapabilityStatement, зарегистрированные и пропущенные инструменты, параметры поиска, операции и примечания к метаданным.

paginate получает одну страницу Bundle, используя возвращённый сервером URL next, проверенный на соответствие источнику FHIR и разрешённым префиксам путей. Когда активен компактный режим и полученная страница содержит больше результатов, paginate автоматически объединяет несколько вышестоящих страниц в один компактный ответ (то же поведение, что и у инструментов поиска ресурсов). Передайте prefetch=false, чтобы отключить объединение и получить одну страницу.

Именованные операции

Инструмент operate вызывает именованные операции FHIR из config/operations.json. Поставляемый каталог операций охватывает клиническую агрегацию, валидацию, поиск документов, терминологические операции, генерацию IPS и сопоставление пациентов. Вы можете расширять, сокращать, заменять или отключать каталог операций без изменения исходного кода.

Терминологические инструменты

Установите FHIR_TERMINOLOGY_BASE_URL, чтобы включить:

Инструмент

Описание

terminology_lookup

Поиск одного кода LOINC или SNOMED CT

code_search

Поиск кодов по текстовому фильтру с поддержкой пагинации

Эти инструменты напрямую вызывают настроенный терминологический сервер. Они не используют учётные данные клинического FHIR-сервера. Используйте терминологическую конечную точку, соответствующую выбранному вами релизу FHIR, например https://tx.fhir.org/r4.

Выполнение Bundle

Установите FHIR_BUNDLE_CAPABILITIES=batch (или batch,transaction), чтобы включить bundle. Этот инструмент отправляет FHIR batch или transaction Bundle и возвращает ответ сервера через стандартный конвейер ответов.

Модель безопасности:

  • Пакеты batch только для чтения (все записи GET) разрешены только с FHIR_BUNDLE_CAPABILITIES=batch.

  • Записи (POST, PUT, PATCH, DELETE) дополнительно требуют FHIR_BUNDLE_WRITES_ENABLED=true и соответствующего действия в FHIR_WRITE_CAPABILITIES.

  • Transaction Bundles требуют явного FHIR_BUNDLE_CAPABILITIES=transaction.

  • Каждая запись предварительно проверяется на соответствие настроенным ресурсам, областям действия SMART и взаимодействиям метаданных. Если хотя бы одна запись не проходит, весь Bundle отклоняется до отправки.

Исключения V1: Условные запросы, системная _history, абсолютные URL и URL $operation внутри записей Bundle не поддерживаются.

История в Bundles: Записи vread (Resource/id/_history/vid), история экземпляра (Resource/id/_history) и история типа (Resource/_history) разрешены в Bundles, когда сервер рекламирует соответствующее взаимодействие и области действия разрешают это. Они считаются записями чтения.

Гейтинг метаданных и областей действия

Если FHIR_METADATA_MODE=off не установлен, fhirHydrant получает CapabilityStatement FHIR-сервера при запуске. В режиме strict:

  • Инструменты ресурсов регистрируются только когда тип ресурса присутствует в /metadata

  • Серверные элементы управления поиском, такие как _count, _sort, _summary, _elements, _include и _revinclude, доступны только если они рекламируются

  • Параметры поиска блокируются, когда сервер их не рекламирует

  • Действия записи требуют как FHIR_WRITE_CAPABILITIES, так и соответствующих взаимодействий CapabilityStatement

  • Именованные операции требуют, чтобы целевой тип ресурса существовал, предоставленная область действия SMART разрешала ресурс, и сама операция была рекламирована в записи CapabilityStatement ресурса

В режиме warn нерекламируемые параметры разрешены с предупреждением, но отсутствующие типы ресурсов всё равно пропускаются. Области действия SMART также проверяются во время выполнения, поэтому инструмент может существовать в схеме и всё равно быть заблокированным областью действия предоставленного токена.

Экономия токенов и формирование ответов

FHIR-ответы часто значительно больше, чем нужно MCP-клиенту. fhirHydrant формирует ответы для экономии токенов после получения, используя серверные управляющие параметры, когда FHIR-сервер их объявляет.

Возможность

Поведение

_count по умолчанию/лимит

По умолчанию _count не подставляется (размер страницы определяет сервер). Установите FHIR_DEFAULT_COUNT, чтобы подставлять значение; FHIR_MAX_COUNT ограничивает явные значения вызывающей стороны (0 = без ограничения)

Объединение страниц

Когда активен компактный режим, сервер последовательно получает несколько вышестоящих страниц, немедленно сжимает каждую и возвращает один объединённый Bundle. Управляется переменными maxResults, prefetch и FHIR_PREFETCH_*

Лимит байт

FHIR_MAX_RESPONSE_BYTES ограничивает каждый JSON-ответ, предназначенный для модели; слишком большие Bundle прозрачно разбиваются на части

Автоповтор

Слишком большие поисковые Bundle сначала пытаются разбиваться локально, затем повторяются с меньшим _count как запасной вариант

FHIRPath

fhirpath фильтрует возвращаемый FHIR JSON локально и возвращает соответствующие узлы в виде массива

Компактный режим

responseMode=compact удаляет типичный «шум» FHIR-конверта и упрощает типы данных

Полный режим

responseMode=full возвращает исходный FHIR JSON

Заблокированный компактный

FHIR_RESPONSE_MODE=compact-locked скрывает responseMode из схемы инструмента

Нативные артефакты

Не-JSON ответы (документы, изображения, DICOM, RTF, HTML, XML, CSV, NDJSON, ZIP, octet-stream) и JSON FHIR Binary нормализуются в метаданный конверт плюс один встроенный текстовый/бинарный ресурс MCP. Ограничивается FHIR_MAX_ARTIFACT_MB (не JSON-лимитом), никогда не разбивается на части и не пропускается через FHIRPath/сжатие/объединение. Аргументы, влияющие только на JSON, игнорируются с примечанием

Компактный вывод — это JSON, ориентированный на ИИ, а не канонический FHIR. Он удаляет или упрощает шум FHIR и распространённые типы данных, такие как meta, narrative, расширения, CodeableConcept, Reference, Quantity, а также более новые типы данных, такие как CodeableReference. FHIRPath выполняется локально; FHIR-сервер никогда не видит выражение. Если оценка не удалась, исходный ответ не возвращается, а возвращается ошибка.

Структурированный конверт ответа

Каждый инструмент данных FHIR (инструменты ресурсов, paginate, operate, bundle, system_history) возвращает единый структурированный конверт, объявленный через outputSchema каждого инструмента и возвращаемый как structuredContent (текстовое содержимое — это тот же конверт в сериализованном виде). Он содержит полезную нагрузку FHIR (data) плюс метаданные: режим ответа, сигнал пагинации hasMore/continuation, статистику Bundle и объединения, а также понятные человеку notes. Полный список полей — это outputSchema инструмента.

Слишком большие ответы разбиваются на части, когда это возможно (data сохраняется, доступно через continuation); если разбиение невозможно, конверт помечается status: "truncated" с опущенным data. Усечение — это успешный, но частичный результат, а не ошибка. Инструменты возможностей и терминологии возвращают свои собственные структурированные формы, а не этот FHIR-конверт.

Объединение страниц

Когда для поиска активен компактный режим (инструменты ресурсов или paginate), сервер последовательно получает несколько вышестоящих страниц FHIR, немедленно сжимает каждую страницу и возвращает один объединённый компактный Bundle. Это сокращает количество обращений к MCP с множества вызовов «следующая страница» до одного.

  • maxResults задаёт цель — сервер прекращает получение после пересечения этого порога (может немного превысить, так как добавляются целые страницы)

  • prefetch=false отключает объединение для одного вызова

  • _count по-прежнему управляет размером вышестоящей страницы FHIR

  • Объединение останавливается при настраиваемых лимитах страниц, записей, байт и времени

  • continuation.url указывает, где остановился сервер; вызовите paginate с responseMode=compact, чтобы продолжить (hasMore указывает, что осталось больше)

  • Запросы, отфильтрованные через FHIRPath, остаются одностраничными (без объединения)

  • responseMode=full всегда возвращает одну вышестоящую страницу

События аудита

Установите FHIR_AUDIT_SINK в любую комбинацию console, file и http.

Приёмник http отправляет каждое событие аудита POST-запросом внешнему коллектору, SIEM или репозиторию аудита FHIR (не самому FHIR-серверу). Установите FHIR_AUDIT_HTTP_URL в адрес назначения и FHIR_AUDIT_HTTP_FORMAT в raw (внутренний JSON аудита с минимальным PHI, для универсальных коллекторов, таких как Splunk HEC или Datadog) или fhir-auditevent (минимальный ресурс FHIR R4 AuditEvent, подходящий для репозиториев аудита в стиле ATNA и нативных для FHIR). Сопоставление fhir-auditevent намеренно лёгкое — это не полный профиль соответствия ATNA/BALP. Необязательное значение FHIR_AUDIT_HTTP_AUTH отправляется дословно как заголовок Authorization. Доставка выполняется по принципу «выстрелил и забыл» с таймаутом 5 секунд; сбои транспорта регистрируются и никогда не влияют на ответы инструментов.

События аудита включают временную метку, инструмент, тип ресурса (если применимо), операцию, статус, длительность, размер ответа, сводку пагинации, ID запроса и необязательного пользователя, аутентифицированного через прокси. По умолчанию они не включают содержимое ресурсов FHIR.

При работе за аутентифицирующим прокси установите FHIR_AUDIT_USER_HEADER в доверенный заголовок идентификации, внедряемый этим прокси:

Распространённые заголовки: Azure EasyAuth X-MS-CLIENT-PRINCIPAL-NAME, OAuth2 Proxy X-Auth-Request-Email, Cloudflare Access Cf-Access-Authenticated-User-Email.

Используйте это только когда прокси удаляет или перезаписывает входящие копии этого заголовка. В противном случае клиенты могут подделать произвольных пользователей аудита.

SMART Backend Auth и ключи

fhirHydrant использует SMART Backend Services: учётные данные клиента плюс подписанное JWT-утверждение. Это бэкенд-доступ к FHIR, а не браузерный SMART standalone-запуск; в пути MCP нет интерактивного перенаправления/входа.

FHIR_ACTIVE_KEY содержит исходный ключ подписи PKCS#8 (RSA, подпись RS384, или EC P-384, подпись ES384). В HTTP-режиме встроенная конечная точка /jwks предоставляет открытые ключи для активного ключа, а также для любых выведенных из эксплуатации ключей, когда FHIR_JWKS_URL не задан. kid для каждого ключа выводится автоматически через усечённый RFC 7638 JWK Thumbprint (первые 12 символов base64url от SHA-256 по каноническим открытым членам JWK) и регистрируется при запуске.

Процедура ротации ключей:

  1. Сгенерируйте новый ключ (RSA-2048 или EC P-384).

  2. Добавьте новый PEM в FHIR_RETIRED_KEYS и переразверните, чтобы JWKS включал оба.

  3. Зарегистрируйте новый kid (регистрируется при запуске) на вашем сервере аутентификации.

  4. Переместите новый PEM в FHIR_ACTIVE_KEY, а старый PEM — в FHIR_RETIRED_KEYS. Переразверните.

  5. После истечения кэшей сервера аутентификации удалите старый ключ из FHIR_RETIRED_KEYS.

Если используется внешний JWKS, опубликуйте новый открытый ключ перед переключением FHIR_ACTIVE_KEY.

Переменные окружения

Полный пример см. в .env.example.

Обязательные

Переменная

Описание

FHIR_BASE_URL

Базовый URL, используемый для получения URL FHIR-сервера и URL токена. Необязателен, когда задан FHIR_SERVER_URL (и, для smart auth, FHIR_TOKEN_URL)

FHIR_CLIENT_ID

ID клиента SMART Backend Services (не нужен, когда FHIR_AUTH=none)

FHIR_ACTIVE_KEY

Ключ подписи PEM в кодировке base64 PKCS#8, RSA или EC P-384 (не нужен, когда FHIR_AUTH=none)

Необязательные

Переменная

По умолчанию

Описание

FHIR_AUTH

smart

smart (SMART Backend Services) или none (без аутентификации, для публичных тестовых конечных точек)

FHIR_RETIRED_KEYS

не задано

Разделённые запятыми base64-кодированные PEM-ключи для ротации JWKS

FHIR_VERSION

R4

Активный релиз FHIR R4+; управляет производным URL, моделью FHIRPath и метаданными компактной модели

FHIR_SERVER_URL

<base>/api/FHIR/<FHIR_VERSION>

Явное переопределение URL FHIR API

FHIR_TOKEN_URL

<base>/oauth2/token

Явное переопределение конечной точки токена

FHIR_JWKS_URL

не задано

Внешний URL JWKS. В HTTP-режиме опустите, чтобы включить встроенный /jwks

MCP_TRANSPORT

http

http или stdio

PORT

5000

Порт прослушивания HTTP

BIND_HOST

0.0.0.0 (или 127.0.0.1 с флагом --dev)

Адрес привязки HTTP

ALLOWED_HOSTS

не задано

Разделённые запятыми имена хостов для защиты от DNS rebinding

FHIR_METADATA_MODE

strict

strict, warn или off для проверки /metadata

FHIR_DEFAULT_COUNT

0

Значение _count по умолчанию, подставляемое в поисковые запросы, когда это разрешено; 0 = сервер решает сам

FHIR_MAX_COUNT

0

Ограничение на явные значения _count, задаваемые вызывающей стороной; 0 = без ограничения

FHIR_MAX_RESPONSE_BYTES

262144

Лимит байтов для JSON-ответов, предназначенных модели; слишком большие Bundle разбиваются на части

FHIR_MAX_ARTIFACT_MB

16

Отдельный байтовый предел (MiB) для тел нативных/двоичных артефактов; не зависит от JSON-лимита (транспортировка base64 ≈ +33%)

FHIR_REQUEST_TIMEOUT_MS

30000

Тайм-аут на одну попытку для исходящих FHIR-запросов

MCP_JSON_LIMIT

4mb

Максимальный принимаемый размер тела MCP-запроса (строка лимита json в Express); увеличьте, если крупные полезные нагрузки записи/bundle отклоняются

MCP_AUTHZ

none

Провайдер авторизации: none или entra. Ограничивает доступ к инструментам для каждого вызывающего (только HTTP + Authorization: Bearer)

MCP_ROLE_PREFIX

FhirHydrant

Префикс для значений выданных ролей (например, FhirHydrant.Patient.Read)

MCP_ENTRA_TENANT_ID

не задано

GUID тенанта Entra (не псевдоним домена); требуется, когда MCP_AUTHZ=entra

MCP_ENTRA_AUDIENCE

не задано

ID приложения API (клиента), ожидаемый в поле aud токена доступа v2; требуется, когда MCP_AUTHZ=entra

FHIR_RESPONSE_MODE

не задано

compact, full или compact-locked; если не задано, поиск по умолчанию использует компактный режим, а прямые чтения — полный

FHIR_WRITE_CAPABILITIES

не задано

Разделённые запятыми действия записи: create, update, patch, delete

FHIR_VALIDATE_WRITES

local

off, local (проверки структуры на стороне клиента) или server (локальная проверка + предварительная проверка $validate на сервере для create/update)

FHIR_WRITE_DRY_RUN

false

Установите true, чтобы проверять и регистрировать операции записи, не выполняя их на FHIR-сервере

FHIR_BUNDLE_CAPABILITIES

не задано

Разделённые запятыми типы Bundle: batch, transaction; включает инструмент bundle

FHIR_BUNDLE_WRITES_ENABLED

false

Установите true, чтобы разрешить записи внутри Bundle (также требует FHIR_WRITE_CAPABILITIES)

FHIR_OPERATIONS

не задано

Разделённые запятыми ключи операций; none отключает все операции каталога. Каталог по умолчанию: everything, lastn, validate, docref, expand, lookup, translate, summary, match

FHIR_TERMINOLOGY_BASE_URL

не задано

Включает инструменты терминологии, например https://tx.fhir.org/r4

FHIR_PAGINATION_PATHS

не задано

Дополнительные допустимые префиксы путей для ссылок пагинации, например FHIRProxy

FHIR_PREFETCH_MAX_PAGES

5

Максимальное количество страниц вышестоящего сервера, загружаемых за один объединённый компактный поиск

FHIR_PREFETCH_MAX_ENTRIES

5000

Максимальное количество записей вышестоящего сервера, накапливаемых до остановки

FHIR_PREFETCH_MAX_BYTES

2097152

Максимальный объём необработанных байтов, загружаемых до остановки

FHIR_PREFETCH_TIMEOUT_MS

25000

Бюджет реального времени для цикла объединения

FHIR_AUDIT_SINK

не задано

Любая комбинация console, file, http

FHIR_AUDIT_FILE

./audit.jsonl

JSONL-файл, используемый, когда включён приёмник аудита file

FHIR_AUDIT_HTTP_URL

не задано

URL назначения для приёмника аудита http; обязателен, когда включён http

FHIR_AUDIT_HTTP_FORMAT

raw

raw (внутренний JSON AuditEvent) или fhir-auditevent (FHIR R4 AuditEvent)

FHIR_AUDIT_HTTP_AUTH

не задано

Значение заголовка Authorization, отправляемое приёмником http без изменений

FHIR_AUDIT_USER_HEADER

не задано

Заголовок пользователя, аутентифицированного через прокси, копируемый в события аудита

LOG_LEVEL

info

Уровень детализации журнала: error, warn, info или debug

Явные значения FHIR_SERVER_URL и FHIR_TOKEN_URL всегда имеют приоритет над производными URL.

Поддержка версий FHIR

Установите FHIR_VERSION, чтобы выбрать активный релиз FHIR R4+. Он управляет производным URL API FHIR, контекстом модели FHIRPath и метаданными компактной модели ответа. Некоторые релизы могут использовать ближайшую совместимую модель FHIRPath. Для терминологии используйте endpoint, соответствующий выбранному релизу FHIR. Журналы запуска подсказывают, когда явные URL FHIR или терминологии, по-видимому, ссылаются на другую версию.

Настройка инструментов и сообщений

Всё, что находится в config/, можно настраивать без изменения исходного кода.

Конфигурация разрешается как частичное перекрытие (partial overlay): для каждого файла ./config/<file> в текущем рабочем каталоге (если присутствует) переопределяет встроенное значение по умолчанию, а всё, что вы опускаете, возвращается к встроенному умолчанию. Поэтому установка через npm работает из коробки, а для настройки вы размещаете папку ./config рядом с местом запуска сервера, содержащую только те файлы, которые хотите изменить.

Есть две степени детализации перекрытия:

  • На уровне файла (resources/*.json, operations.json, search-controls.json, core-tools.json, instructions/*): предоставленный вами файл полностью заменяет встроенный. Новый файл ресурса (например, ./config/resources/myresource.json) добавляет инструмент. Перекрытие может переопределять и добавлять, но не может удалить встроенный ресурс — чтобы поставлять строго минимальный каталог, удалите встроенные файлы config/resources/ (см. пример compose).

  • На уровне ключа (messages/*.json): локальный файл переопределяет только отдельные ключи, которые он содержит; все остальные ключи возвращаются к встроенному умолчанию. Так вы можете перенастроить одно описание или сообщение без копирования всего файла. Неизвестные ключи, пустые значения и некорректный JSON быстро завершают работу при старте, чтобы выявить опечатки.

Файлы messages/*.json читаются один раз при запуске процесса. Чтобы изменения вступили в силу, требуется перезапуск сервера (а для схем инструментов или инструкций — повторное подключение клиента). Горячая перезагрузка ресурсов, элементов управления поиском и операций в режиме разработки описана ниже.

Файл

Назначение

resources/*.json

Инструменты ресурсов FHIR (один файл на ресурс): параметры поиска, поведение прямого чтения и правила requireOneOf

operations.json

Каталог именованных операций для operate (описания и примечания для каждой операции)

search-controls.json

Описания для _count, _sort, _summary, _elements, _include, _revinclude, _lastUpdated, fhirpath, responseMode, maxResults и prefetch

messages/output-schema.json

Описания для каждого поля outputSchema инструмента (перекрытие по ключу)

messages/input-schema.json

Описания для сгенерированных входных параметров ресурсов (_id, _vid, _since, _at, action, body) и заголовка и параметров инструмента operate (перекрытие по ключу)

instructions/manifest.json

Упорядоченный список фрагментов инструкций для сборки, каждый с опциональным условием when (terminology, writes, operations, bundle). Пользовательские сборки изменяют порядок, добавляют или удаляют разделы, редактируя этот файл.

instructions/*.md

Фрагменты инструкций, на которые ссылается манифест. Разделы с условиями включаются только тогда, когда соответствующая функция включена; токен {{OPERATIONS_LIST}} заменяется актуальным каталогом операций.

messages/*.json

Пользовательские сообщения, ошибки и примечания к ответам (перекрытие по ключу, разбито по доменам: core, write, operations, terminology, bundle, artifact)

core-tools.json

Описания встроенных инструментов и подсказки по параметрам

Схема определения ресурса

Каждый файл в config/resources/ представляет собой один объект определения ресурса. Файлы сканируются в порядке имён; имя файла обычно является именем ресурса в нижнем регистре (например, patient.json). Каждый объект имеет следующие поля:

Поле

Тип

Описание

resource

string

Тип ресурса FHIR

toolName

string

Имя инструмента MCP; должно быть уникальным

description

string

Описание инструмента

supportsDirectRead

boolean

Включает GET /ResourceType/{id} через _id

searchParams

Record<string,string>

Параметры поиска FHIR и их описания

requireOneOf

(string | string[])[]

Для поиска требуется хотя бы один вариант. Строка — один обязательный параметр; вложенный массив — набор параметров, где каждый параметр обязателен. ["patient"] принимает patient; [["given","family"],["identifier"]] принимает given+family вместе или identifier

Значения searchParams — это описания, а не полная модель возможностей FHIR. Поведение поиска, специфичное для сервера, всё равно может применяться.

Горячая перезагрузка

В режиме разработки (NODE_ENV не равен production) папка config/resources/, search-controls.json и operations.json отслеживаются. Некорректный JSON сохраняет последний допустимый снимок. Перезагрузка с существенными изменениями применяется транзакционно: когда производные SMART-области изменяются, новый токен получается до фиксации новых определений и регистраций инструментов, так что неудачное получение оставляет работающий каталог нетронутым. Добавление/удаление инструментов, изменения схем операций и имён параметров перерегистрируются на лету — перезапуск не требуется. Сохранения без семантических изменений не вызывают обновления. Производственный режим читает конфигурацию один раз при запуске, но изменение /metadata во время выполнения (через capabilities(refresh=true)) или изменение SMART-областей бэкенда при обновлении токена повторно оценивает доступные инструменты во всех режимах.

Одна граница неизбежна: список инструментов и схемы обновляются на лету, но instructions сервера отправляются один раз во время MCP initialize и не могут быть заменены в существующем соединении. Чтобы получить изменённый текст инструкций, клиент должен переподключиться/повторно инициализироваться.

Транспорты

Stdio

Установите MCP_TRANSPORT=stdio. stdout зарезервирован для протокола MCP; логи перенаправляются в stderr. Для развёртываний на stdio используйте внешний FHIR_JWKS_URL.

Streamable HTTP

HTTP-транспорт не сохраняет состояние и предоставляет MCP по адресу:

POST http://localhost:5000/mcp
Accept: application/json, text/event-stream
Content-Type: application/json

Конфигурация MCP-клиента:

{
   "mcpServers": {
      "fhirhydrant": {
         "url": "http://localhost:5000/mcp"
      }
   }
}

GET /health возвращает снимок готовности без PHI:

{
   "status": "ok",
   "mcp": true,
   "metadata": true,
   "tools": 23,
   "auth": true,
   "tokenExpiresIn": 287
}

Когда авторизация включена, authz сообщает активного провайдера, а tools опускается, поскольку количество зарегистрированных инструментов зависит от вызывающей стороны.

Используйте обратный прокси для TLS и аутентификации пользователей при публикации HTTP за пределами localhost. Установите ALLOWED_HOSTS при привязке к публичному интерфейсу.

Авторизация по вызывающему (Entra, опционально)

По умолчанию (MCP_AUTHZ=none) каждый вызывающий видит полный набор инструментов, ограниченный только /metadata и SMART-областями бэкенда. Установка MCP_AUTHZ=entra добавляет опциональный слой на уровне вызывающего: каждый запрос /mcp должен содержать Authorization: Bearer <token>, выпущенный Microsoft Entra, а роли приложения (App Roles) вызывающего определяют, какие инструменты будут построены для этого запроса. Это авторизация только на уровне MCP — она никогда не заменяет собственную авторизацию FHIR-сервера и может только вычитать из того, что уже разрешают токен SMART бэкенда и конфигурация.

В манифесте регистрации приложения API должно быть установлено значение requestedAccessTokenVersion равное 2. Провайдер проверяет издателей v2 для конкретного тенанта и ожидает, что MCP_ENTRA_AUDIENCE — это идентификатор клиента приложения API.

Инструменты, для которых у вызывающего нет роли, вообще не регистрируются — они отсутствуют в tools/list, а не просто блокируются. Вспомогательные инструменты (capabilities, paginate, terminology_lookup, code_search) никогда не ограничиваются.

Значения ролей приложения (с префиксом по умолчанию FhirHydrant):

Роль

Предоставляет

FhirHydrant.<Resource>.Read

search, read, vread, history для этого ресурса

FhirHydrant.<Resource>.Write

действия чтения плюс create, update, patch, delete (с учётом FHIR_WRITE_CAPABILITIES)

FhirHydrant.Operation.<key>

именованную операцию через инструмент operate (например, FhirHydrant.Operation.everything)

FhirHydrant.Bundle

инструмент bundle

FhirHydrant.SystemHistory.Read

общесистемный инструмент system_history

FhirHydrant.Admin

всё вышеперечисленное, но всё ещё ограничено SMART-областями бэкенда, /metadata и конфигурацией write/bundle/operation

Требуется HTTP-транспорт; MCP_AUTHZ=entra вместе с MCP_TRANSPORT=stdio приводит к ошибке при запуске. Отсутствующие или недействительные bearer-токены получают 401.

Добавление провайдера авторизации

Entra — единственный поставляемый провайдер, но слой авторизации нейтрален к провайдерам. Это расширение исходного кода, а не плагин времени выполнения: npm-пакет поставляется только с bin/server.js (провайдеры встроены в него), поэтому добавление нового провайдера означает форк или клонирование репозитория и пересборку.

Общий конвейер не зависит от провайдера — провайдер лишь сопоставляет заголовок Authorization с { subject, roles }. Словарь ролей (.Read/.Write/Operation.<key>/Bundle/SystemHistory.Read/Admin) и обработка MCP_ROLE_PREFIX применяются функцией decideAuthz для каждого провайдера.

Чтобы добавить провайдера (например, auth0), достаточно двух правок:

  1. Создайте ts/mcp/authz/auth0.ts, экспортирующий AuthzProvider — реализуйте validate(authorization), чтобы он возвращал { subject, roles } (бросайте исключение для отклонения), и опционально validateConfig() для быстрого отказа при отсутствии переменных окружения провайдера. Держите все переменные окружения провайдера внутри этого модуля; не добавляйте поля в Config.

  2. Добавьте одну запись в ts/mcp/authz/registry.ts: auth0: () => import("./auth0.ts").then((m) => m.auth0Provider).

Вот и всё. Тип AuthzMode, парсер MCP_AUTHZ и его сообщение об ошибке автоматически выводятся из ключей реестра, так что MCP_AUTHZ=auth0 просто работает с полной типобезопасностью — никакой другой файл менять не нужно.

Примеры развёртывания

В каталоге examples/ находятся автономные примеры развёртывания для Docker Compose, обратного прокси (Caddy), Azure Container Apps, Azure App Service и Kubernetes. Каждый включает Dockerfile, который устанавливает из npm, и оверлей config/, демонстрирующий, как переопределять различные файлы конфигурации.

Разработка

# dev server
npm run dev

# type-check
npm run check

# build and run
npm run build
npm start

Результат сборки помещается в bin/server.js.

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    C
    maintenance
    Provides seamless integration with FHIR APIs, enabling AI/LLM tools to search, retrieve, and analyze clinical healthcare data with support for SMART-on-FHIR authentication and multiple transport protocols.
    7
    134
    Apache 2.0
  • F
    license
    Not graded
    quality
    D
    maintenance
    Enables AI assistants to securely interact with FHIR R4 servers for clinical decision support workflows, including PlanDefinition execution, FHIR resource management, terminology services, and Questionnaire/StructureMap transformation via Matchbox.
    1

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/faulkj/fhirHydrant'

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