fhirHydrant
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-ресурсов |
| Сервер рекламирует системное взаимодействие | Получение истории изменений на уровне системы для всех типов ресурсов |
| Всегда зарегистрирован | Просмотр сводки CapabilityStatement, зарегистрированных инструментов, пропущенных инструментов, параметров поиска, операций и примечаний к метаданным |
| Всегда зарегистрирован | Получение следующей страницы FHIR Bundle с использованием возвращённого сервером URL |
| Хотя бы одна именованная операция проходит гейтинг | Вызов настроенных именованных операций FHIR для клинических данных, терминологии, IPS, сопоставления, валидации или пользовательских рабочих процессов |
| Установлен | Отправка FHIR batch или transaction Bundle; записи требуют дополнительного согласия |
| Установлен | Поиск одного кода LOINC или SNOMED CT |
| Установлен | Поиск кодов 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 доступен, когда ресурс имеет 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, чтобы включить:
Инструмент | Описание |
| Поиск одного кода LOINC или SNOMED CT |
| Поиск кодов по текстовому фильтру с поддержкой пагинации |
Эти инструменты напрямую вызывают настроенный терминологический сервер. Они не используют
учётные данные клинического 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-сервер их объявляет.
Возможность | Поведение |
| По умолчанию |
Объединение страниц | Когда активен компактный режим, сервер последовательно получает несколько вышестоящих страниц, немедленно сжимает каждую и возвращает один объединённый Bundle. Управляется переменными |
Лимит байт |
|
Автоповтор | Слишком большие поисковые Bundle сначала пытаются разбиваться локально, затем повторяются с меньшим |
FHIRPath |
|
Компактный режим |
|
Полный режим |
|
Заблокированный компактный |
|
Нативные артефакты | Не-JSON ответы (документы, изображения, DICOM, RTF, HTML, XML, CSV, NDJSON, ZIP, octet-stream) и JSON FHIR Binary нормализуются в метаданный конверт плюс один встроенный текстовый/бинарный ресурс MCP. Ограничивается |
Компактный вывод — это 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) и регистрируется при запуске.
Процедура ротации ключей:
Сгенерируйте новый ключ (RSA-2048 или EC P-384).
Добавьте новый PEM в
FHIR_RETIRED_KEYSи переразверните, чтобы JWKS включал оба.Зарегистрируйте новый
kid(регистрируется при запуске) на вашем сервере аутентификации.Переместите новый PEM в
FHIR_ACTIVE_KEY, а старый PEM — вFHIR_RETIRED_KEYS. Переразверните.После истечения кэшей сервера аутентификации удалите старый ключ из
FHIR_RETIRED_KEYS.
Если используется внешний JWKS, опубликуйте новый открытый ключ перед переключением FHIR_ACTIVE_KEY.
Переменные окружения
Полный пример см. в .env.example.
Обязательные
Переменная | Описание |
| Базовый URL, используемый для получения URL FHIR-сервера и URL токена. Необязателен, когда задан |
| ID клиента SMART Backend Services (не нужен, когда |
| Ключ подписи PEM в кодировке base64 PKCS#8, RSA или EC P-384 (не нужен, когда |
Необязательные
Переменная | По умолчанию | Описание |
|
|
|
| не задано | Разделённые запятыми base64-кодированные PEM-ключи для ротации JWKS |
|
| Активный релиз FHIR R4+; управляет производным URL, моделью FHIRPath и метаданными компактной модели |
|
| Явное переопределение URL FHIR API |
|
| Явное переопределение конечной точки токена |
| не задано | Внешний URL JWKS. В HTTP-режиме опустите, чтобы включить встроенный |
|
|
|
|
| Порт прослушивания HTTP |
|
| Адрес привязки HTTP |
| не задано | Разделённые запятыми имена хостов для защиты от DNS rebinding |
|
|
|
|
| Значение |
|
| Ограничение на явные значения |
|
| Лимит байтов для JSON-ответов, предназначенных модели; слишком большие Bundle разбиваются на части |
|
| Отдельный байтовый предел (MiB) для тел нативных/двоичных артефактов; не зависит от JSON-лимита (транспортировка base64 ≈ +33%) |
|
| Тайм-аут на одну попытку для исходящих FHIR-запросов |
|
| Максимальный принимаемый размер тела MCP-запроса (строка лимита json в Express); увеличьте, если крупные полезные нагрузки записи/bundle отклоняются |
|
| Провайдер авторизации: |
|
| Префикс для значений выданных ролей (например, |
| не задано | GUID тенанта Entra (не псевдоним домена); требуется, когда |
| не задано | ID приложения API (клиента), ожидаемый в поле |
| не задано |
|
| не задано | Разделённые запятыми действия записи: |
|
|
|
|
| Установите |
| не задано | Разделённые запятыми типы Bundle: |
|
| Установите |
| не задано | Разделённые запятыми ключи операций; |
| не задано | Включает инструменты терминологии, например |
| не задано | Дополнительные допустимые префиксы путей для ссылок пагинации, например |
|
| Максимальное количество страниц вышестоящего сервера, загружаемых за один объединённый компактный поиск |
|
| Максимальное количество записей вышестоящего сервера, накапливаемых до остановки |
|
| Максимальный объём необработанных байтов, загружаемых до остановки |
|
| Бюджет реального времени для цикла объединения |
| не задано | Любая комбинация |
|
| JSONL-файл, используемый, когда включён приёмник аудита |
| не задано | URL назначения для приёмника аудита |
|
|
|
| не задано | Значение заголовка Authorization, отправляемое приёмником |
| не задано | Заголовок пользователя, аутентифицированного через прокси, копируемый в события аудита |
|
| Уровень детализации журнала: |
Явные значения 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 читаются один раз при запуске процесса. Чтобы изменения вступили в силу, требуется перезапуск сервера (а для схем инструментов или инструкций — повторное подключение клиента). Горячая перезагрузка ресурсов, элементов управления поиском и операций в режиме разработки описана ниже.
Файл | Назначение |
| Инструменты ресурсов FHIR (один файл на ресурс): параметры поиска, поведение прямого чтения и правила |
| Каталог именованных операций для |
| Описания для |
| Описания для каждого поля |
| Описания для сгенерированных входных параметров ресурсов ( |
| Упорядоченный список фрагментов инструкций для сборки, каждый с опциональным условием |
| Фрагменты инструкций, на которые ссылается манифест. Разделы с условиями включаются только тогда, когда соответствующая функция включена; токен |
| Пользовательские сообщения, ошибки и примечания к ответам (перекрытие по ключу, разбито по доменам: core, write, operations, terminology, bundle, artifact) |
| Описания встроенных инструментов и подсказки по параметрам |
Схема определения ресурса
Каждый файл в config/resources/ представляет собой один объект определения ресурса. Файлы сканируются в порядке имён; имя файла обычно является именем ресурса в нижнем регистре (например, patient.json). Каждый объект имеет следующие поля:
Поле | Тип | Описание |
|
| Тип ресурса FHIR |
|
| Имя инструмента MCP; должно быть уникальным |
|
| Описание инструмента |
|
| Включает |
|
| Параметры поиска FHIR и их описания |
|
| Для поиска требуется хотя бы один вариант. Строка — один обязательный параметр; вложенный массив — набор параметров, где каждый параметр обязателен. |
Значения 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):
Роль | Предоставляет |
| search, read, vread, history для этого ресурса |
| действия чтения плюс create, update, patch, delete (с учётом |
| именованную операцию через инструмент |
| инструмент |
| общесистемный инструмент |
| всё вышеперечисленное, но всё ещё ограничено SMART-областями бэкенда, |
Требуется 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), достаточно двух правок:
Создайте
ts/mcp/authz/auth0.ts, экспортирующийAuthzProvider— реализуйтеvalidate(authorization), чтобы он возвращал{ subject, roles }(бросайте исключение для отклонения), и опциональноvalidateConfig()для быстрого отказа при отсутствии переменных окружения провайдера. Держите все переменные окружения провайдера внутри этого модуля; не добавляйте поля вConfig.Добавьте одну запись в
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.
This server cannot be installed
Maintenance
Related MCP Connectors
Hosted MCP server for the Healthie EHR & telehealth API: patients, appointments, charting, tasks.
Securely access and manage FHIR healthcare data stored in Medplum.
Governed MCP gateway: one endpoint for your tools, with credential custody and audit log.
Governed data discovery, exact queries, decisions, simulations, and runtime utilities over MCP.
Related MCP Servers
- AlicenseAqualityCmaintenanceProvides 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.7134Apache 2.0
- FlicenseNot gradedqualityDmaintenanceEnables 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
- AlicenseNot gradedqualityDmaintenanceEnables interaction with FHIR servers to access, search, and manage FHIR resources, including appointment scheduling and cancellation.1MIT

LangCare MCP FHIR Serverofficial
AlicenseNot gradedqualityDmaintenanceEnterprise-grade MCP Server for FHIR-based EMRs. Enables AI agents to read, search, create, and update any FHIR R4 resource across major EHR systems like EPIC, Cerner, and OpenEMR.14753MIT
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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