Skip to main content
Glama
ysnr-dev

fhir-mcp-server

by ysnr-dev

fhir-mcp-server

FHIR R4 サーバー(JP-Core 準拠の fhir-server や HAPI FHIR 等)に接続する MCP(Model Context Protocol)サーバーです。Claude Desktop / Claude Code などの MCP クライアントから、FHIR データを自然言語で検索・参照・(オプトインで)書き込みできます。

  • fhir-server とはリポジトリ分離(接点は HTTP + Bearer トークンのみ)

  • SMART Backend Services(OAuth2 client_credentials + system/* スコープ)のクライアントとして動作

  • FHIR_BASE_URL とクレデンシャルの差し替えで任意の FHIR R4 サーバーに接続可能

セットアップ

Node.js 20+ が必要です。

npm install
npm run build

Related MCP server: FHIRfly MCP Server

Docker / docker compose で動かす

Node.js をホストに入れずに動かす場合は Docker イメージを使います。MCP の stdio サーバーなので常駐(up)は不要で、クライアントが必要なときに docker compose run で起動します。

docker compose build

動作確認(手動で JSON-RPC を流す代わりに、後述のクライアント登録をしてもよい):

docker compose run --rm -T fhir-mcp
  • 既定の接続先は http://host.docker.internal:3000(= ホストの localhost:3000)。fhir-server をホストで直接動かしていても、docker compose(ポート 3000 公開)で動かしていてもそのままつながります

  • 接続先やクレデンシャルは環境変数で上書きできます: FHIR_BASE_URL=... FHIR_CLIENT_ID=... docker compose run --rm -T fhir-mcp

  • fhir-server(Rails)側は HostAuthorization で host.docker.internal を許可している必要があります(development.rb の config.hosts << "host.docker.internal")

Docker 経由で Claude Code に登録する場合:

claude mcp add fhir -- docker compose -f /path/to/fhir-mcp-server/compose.yaml run --rm -T fhir-mcp

Claude Desktop の場合:

{
  "mcpServers": {
    "fhir": {
      "command": "docker",
      "args": [
        "compose", "-f", "/path/to/fhir-mcp-server/compose.yaml",
        "run", "--rm", "-T", "fhir-mcp"
      ]
    }
  }
}

Claude クライアントへの接続

Claude Code

claude mcp add fhir -- node /path/to/fhir-mcp-server/dist/index.js

環境変数を渡す場合:

claude mcp add fhir \
  -e FHIR_BASE_URL=http://localhost:3000 \
  -e FHIR_CLIENT_ID=... \
  -e FHIR_CLIENT_SECRET=... \
  -- node /path/to/fhir-mcp-server/dist/index.js

Claude Desktop(claude_desktop_config.json)

{
  "mcpServers": {
    "fhir": {
      "command": "node",
      "args": ["/path/to/fhir-mcp-server/dist/index.js"],
      "env": {
        "FHIR_BASE_URL": "http://localhost:3000",
        "FHIR_CLIENT_ID": "...",
        "FHIR_CLIENT_SECRET": "..."
      }
    }
  }
}

Web版(リモート HTTP MCP / スマホ Claude アプリ向け)

Claude Desktop / Code は stdio でローカル起動しますが、スマホの Claude アプリは ローカルプロセスを起動できず、公開 HTTPS に常駐するリモート MCP サーバー (カスタムコネクタ)+ OAuth にしか接続できません。そのための HTTP エントリポイント dist/http.js を用意しています(stdio 版 dist/index.js はそのまま併存)。

  • トランスポート: MCP Streamable HTTP(/mcp に POST/GET/DELETE)

  • 認可: 外部 IdP(Auth0 等)へ委譲する OAuth。/.well-known/oauth-* メタデータと authorize/token/register の proxy を自動提供し、/mcp は Bearer トークンで保護

  • このフェーズでは OAuth は「接続の入口」を守るだけ。認証ユーザー単位の FHIR アクセス制御(SMART on FHIR user/*/patient/* 相当)は本番データ移行時に対応予定。 FHIR への接続は従来通り固定の SMART Backend Services クレデンシャルを使います (デモ・評価データ前提)。

起動

npm run build
PUBLIC_URL=https://your-host \
OAUTH_ISSUER_URL=https://YOUR_TENANT.auth0.com/ \
OAUTH_AUTHORIZATION_URL=https://YOUR_TENANT.auth0.com/authorize \
OAUTH_TOKEN_URL=https://YOUR_TENANT.auth0.com/oauth/token \
OAUTH_JWKS_URL=https://YOUR_TENANT.auth0.com/.well-known/jwks.json \
OAUTH_AUDIENCE=https://your-host/api \
FHIR_BASE_URL=http://localhost:3000 \
node dist/http.js

docker compose で常駐起動する場合(.env に上記を書いておく):

docker compose up fhir-mcp-http    # http://localhost:8080/mcp で待受

環境変数はローカルでは .env(サンプル: .env.example)にまとめ、 Node 20+ の --env-file で読み込めます:

npm run build && node --env-file=.env dist/http.js

外部 IdP(Auth0)の設定

詳細手順は docs/auth0-setup.md を参照。要点:

  1. API を作成し Identifier を OAUTH_AUDIENCE に設定。

  2. テナントの Default Audience をその Identifier に設定(これをしないと Auth0 が JWT ではなく opaque トークンを発行し検証に失敗する — MCP × Auth0 の典型的な落とし穴)。

  3. Dynamic Client Registration を有効化し、ログイン接続を domain level に昇格 (Claude アプリがクライアント自己登録するため)。OAUTH_REGISTRATION_URL も設定。

  4. .well-known/openid-configuration の値を OAUTH_ISSUER_URL 等に写す。 IdP は Google / Cognito 等にも差し替え可能。

スマホの前に、M2M トークンで /mcp の Bearer 検証が通ることを確認できます (手順は上記ドキュメント参照)。

Cloud Run へのデプロイ(想定)

gcloud run deploy fhir-mcp-server \
  --source . --command node,dist/http.js \
  --set-env-vars PUBLIC_URL=https://SERVICE_URL,OAUTH_ISSUER_URL=...,OAUTH_AUDIENCE=...,FHIR_BASE_URL=...

PORT は Cloud Run が注入します(HTTP_PORT 未設定時のフォールバックとして利用)。 scale-to-zero でデモのコストを最小化できます。

Render へのデプロイ(Blueprint / Docker)

render.yaml(Blueprint)を同梱しています。既存 Dockerfile を使い、起動コマンドを http 版に上書きする構成です。

  1. リポジトリを Render に接続し、Blueprint から render.yaml を読み込む。

  2. sync: false の環境変数(OAUTH_* / FHIR_* / PUBLIC_URL)を Render ダッシュボードで設定。

  3. 初回デプロイで https://<service>.onrender.com が発行されるので、それを PUBLIC_URL (メタデータ用)に設定して再デプロイ。IdP 側の Allowed Callback にもこの URL を登録。

  4. スマホ Claude アプリのカスタムコネクタに https://<service>.onrender.com/mcp を登録。

注意点(Free プラン):

  • 15分無アクセスでスリープし、次アクセスでコールドスタート(数十秒)。初回接続が 遅延/タイムアウトすることがある。安定させたい場合は render.yamlplanstarter に変更(常時起動)。

  • セッションはメモリ保持のため、インスタンス再起動で切断される(低トラフィックのデモは問題なし)。

  • PORT は Render が注入(HTTP_PORT 未設定時のフォールバックで対応済み)。

スマホ Claude アプリへの登録

Claude アプリの「カスタムコネクタ」に PUBLIC_URL(= https://SERVICE_URL/mcp)を登録し、 OAuth ログインを済ませると、get_capabilities / search_fhir 等が実機で使えます。

設定(環境変数)

変数

既定

説明

FHIR_BASE_URL

http://localhost:3000

接続先 FHIR サーバー

FHIR_CLIENT_ID / FHIR_CLIENT_SECRET

なし

SMART Backend Services のクレデンシャル。両方未設定なら無認証モード(Authorization ヘッダーを送らない。fhir-server の FHIR_AUTH_ENABLED=false 環境向け)

FHIR_MCP_ALLOW_WRITES

false

true のときだけ書き込みツール(create/update/patch)を登録

FHIR_MCP_MAX_COUNT

50

検索 _count の上限

Web版(HTTP)の追加設定

変数

既定

説明

HTTP_PORT / PORT

8080

HTTP 待受ポート(PORT は Cloud Run 用フォールバック)

PUBLIC_URL

(必須)

このサーバーの公開 URL。OAuth メタデータ・リソース識別子に使用

OAUTH_ISSUER_URL

(必須)

外部 IdP の issuer

OAUTH_AUTHORIZATION_URL

(必須)

IdP の authorization エンドポイント

OAUTH_TOKEN_URL

(必須)

IdP の token エンドポイント

OAUTH_JWKS_URL

(必須)

アクセストークン検証用の JWKS

OAUTH_AUDIENCE

(必須)

アクセストークンに期待する aud

OAUTH_REGISTRATION_URL

なし

IdP の Dynamic Client Registration エンドポイント(任意)

認証(SMART Backend Services)

FHIR_CLIENT_ID / FHIR_CLIENT_SECRET を設定すると、POST {FHIR_BASE_URL}/oauth/tokengrant_type=client_credentials でアクセストークンを取得します。

  • トークンは expires_in の 90% 経過で先回り再取得

  • API が 401 を返した場合は 1 回だけトークンを再取得してリトライ

  • トークン・シークレットはログに出力しません

fhir-server 側のクライアント登録例:

bin/rails "fhir:register_client[fhir-mcp-server,system/*.read]"
# 書き込みも許可する場合は system/*.write スコープを付与

ツール一覧

参照系(常時登録)

ツール

対応エンドポイント

説明

get_capabilities

GET /metadata

対応リソース・検索パラメータ・オペレーションの要約。使い方の自己発見の起点

search_fhir

GET /{type}?...

検索。チェーン検索・_has_include 等は params でそのまま透過

read_fhir

GET /{type}/{id}

単一リソース取得

patient_everything

GET /Patient/{id}/$everything

患者コンパートメント一括取得(_type/_since 対応)

get_history

GET [/{type}[/{id}]]/_history

インスタンス/タイプ/システムレベルの履歴

validate_fhir

POST /{type}/$validate

保存せずにリソースを検証

書き込み系(FHIR_MCP_ALLOW_WRITES=true のときのみ登録)

ツール

対応エンドポイント

説明

create_fhir

POST /{type}

作成(If-None-Exist による条件付き作成対応)

update_fhir

PUT /{type}/{id}

全置換更新(If-Match による楽観ロック対応)

patch_fhir

PATCH /{type}/{id}

JSON Patch(RFC 6902)による部分更新

delete はツールとして提供しません(AI からの破壊的操作は初期スコープ外)。

トークン消費を抑えるコツ

検索結果の Bundle はそのまま返さず、{ total, returned, hasNextPage, resources } に整形して返します。それでも大きい場合は件数を切り詰め、絞り込みのガイダンスを付けます。以下を活用してください:

  • _elements=id,name,birthDate — 必要なフィールドだけ取得

  • _summary=true — サマリー要素のみ取得

  • _count — ページサイズを絞る(既定 20)

  • patient_everything では types / since で範囲を限定

開発

npm run dev        # tsx で直接実行
npm test           # unit テスト(fetch モック)
npm run lint       # biome
npm run build      # tsc → dist/

integration テスト

実サーバー相手の e2e は FHIR_INTEGRATION_BASE_URL を設定したときだけ実行されます:

# fhir-server を docker compose 等で起動しておく
FHIR_INTEGRATION_BASE_URL=http://localhost:3000 npm test

# 認証ありモードを試す場合
FHIR_INTEGRATION_BASE_URL=http://localhost:3000 \
FHIR_INTEGRATION_CLIENT_ID=... \
FHIR_INTEGRATION_CLIENT_SECRET=... \
npm test

アーキテクチャ

MCP クライアント(Claude 等)
        │ stdio
        ▼
fhir-mcp-server
  ├── src/index.ts          エントリポイント(stdio transport)
  ├── src/http.ts           エントリポイント(Streamable HTTP transport + OAuth)
  ├── src/auth.ts           外部 IdP へ委譲する OAuth プロバイダ・JWT 検証
  ├── src/server.ts         McpServer 構築・ツール登録(トランスポート非依存)
  ├── src/config.ts         環境変数の読み込み・検証
  ├── src/fhir-client.ts    FHIR REST 呼び出し(fhir+json、OperationOutcome 整形、401 リトライ)
  ├── src/token-manager.ts  SMART トークン管理(先回り更新)
  ├── src/format.ts         Bundle / CapabilityStatement の要約整形
  └── src/tools/*.ts        ツール実装(薄い層)
        │ HTTP(S) + Authorization: Bearer
        ▼
FHIR R4 サーバー(fhir-server / HAPI など)

設計の背景・rationale は docs/DESIGN.md を参照してください。

Available Tools

6 tools
get_capabilitiesGet FHIR server capabilitiesA
Read-only

Fetch the FHIR server's CapabilityStatement (GET /metadata) and return a compact summary: supported resource types, interactions, search parameters, and operations. Call this first to discover what the server supports.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare readOnlyHint=true, and description adds that it returns a compact summary of resource types, interactions, search parameters, and operations. No contradictions. Slightly enhanced beyond annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two concise sentences, front-loaded with action ('Fetch'), no wasted words. Perfectly structured.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no parameters, annotations, and no output schema, the description sufficiently explains the return value (compact summary of capabilities). Complete enough for a simple read-only discovery tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

No parameters exist, so no need for parameter explanation. Schema coverage is 100%. Baseline score of 4 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description clearly states it fetches the CapabilityStatement and returns a compact summary of capabilities. Specifies verb 'Fetch' and resource 'FHIR server's CapabilityStatement'. Differentiates from sibling tools like search_fhir, read_fhir etc.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly says 'Call this first to discover what the server supports', providing clear usage context. Lacks explicit when-not or alternative tools but is adequate for a discovery tool.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_historyGet resource historyA
Read-only

Fetch version history. With resourceType and id: history of one resource (GET /{type}/{id}/_history). With only resourceType: history across that type. With neither: system-wide history.

ParametersJSON Schema
NameRequiredDescriptionDefault
idNoLogical id (requires resourceType)
countNoEntries per page (default 20, capped at 50)
sinceNoOnly versions created after this instant (ISO 8601)
resourceTypeNoFHIR resource type (omit for system-level history)

TDQS

A4.1/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Description adds implementation details (endpoint patterns) beyond the readOnlyHint annotation, but does not explain what the history response contains (e.g., version entries, ordering) or pagination behavior beyond the count parameter.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three concise sentences, front-loaded with the primary purpose, no redundancy or unnecessary detail.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Description is mostly complete for a read operation with readOnlyHint, but lacks details about the return format (no output schema) and does not mention that the response is typically a Bundle of history entries, which would aid an agent in processing the result.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% with descriptive parameter descriptions, but the tool description adds meaningful context by explaining the three usage modes and how parameters relate (e.g., id requires resourceType), which goes beyond the schema's individual field descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description clearly states it fetches version history and specifies three distinct modes based on parameter combinations (with id+resourceType, only resourceType, neither). This distinguishes it from siblings like search_fhir and read_fhir, which serve different purposes.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Description provides explicit context for when to use each combination of parameters, but does not indicate when NOT to use the tool or mention alternative tools for similar tasks.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

patient_everythingFetch a patient's full recordA
Read-only

Fetch all resources in a patient's compartment (GET /Patient/{id}/$everything): conditions, observations, encounters, medications, etc. Use types to limit resource types and since to limit to recently-updated resources — both are recommended to keep responses manageable.

ParametersJSON Schema
NameRequiredDescriptionDefault
countNoResults per page (default 20, capped at 50)
sinceNoOnly resources updated after this instant (ISO 8601, e.g. 2026-01-01T00:00:00Z)
typesNoRestrict to these resource types, e.g. ["Observation", "Condition"]
patientIdYesLogical id of the Patient

TDQS

A4.2/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true. The description adds the behavioral context that it fetches a large bundle of resources, but does not detail pagination or performance implications. Since annotations cover the safety profile, a 3 is appropriate.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two sentences with no filler. The first sentence defines purpose and endpoint; the second gives actionable parameter guidance. It is front-loaded and every word earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool that returns a large bundle of resources, the description covers the key points: what is returned, optional filters, and the endpoint. Without an output schema, it could mention pagination or response format, but it is sufficient for a read-only operation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% so baseline is 3. The description adds value by explaining that `types` and `since` are recommended for limiting response size, providing context beyond the schema descriptions. This justifies a 4.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states 'Fetch all resources in a patient's compartment' with specific examples (conditions, observations, etc.) and the FHIR endpoint. It distinguishes from sibling tools like read_fhir (single resource) and search_fhir (query-based).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description recommends using `types` and `since` to keep responses manageable, providing explicit guidance for efficient use. It implies this is for comprehensive patient data retrieval but does not explicitly contrast with siblings for when to use alternatives.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

read_fhirRead a FHIR resourceA
Read-only

Read a single resource by type and id (GET /{resourceType}/{id}).

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesLogical id of the resource
resourceTypeYesFHIR resource type, e.g. Patient

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true. The description adds the HTTP method and URL pattern (GET /{resourceType}/{id}), providing additional behavioral context beyond annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, front-loaded sentence that efficiently conveys the tool's purpose without any wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's simplicity (read by type and ID), the description is complete. It covers the purpose, HTTP method, and URL pattern. Output schema is not needed for such a tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% with both parameters having descriptions. The description reiterates 'by type and id' but does not add new meaning beyond the schema. Baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states 'Read a single resource by type and id', with a specific verb and resource. It distinguishes from sibling tools like search_fhir and patient_everything which serve different purposes.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies when to use (to read a single resource) by specifying 'Read a single resource by type and id'. It does not explicitly list alternatives but is clear in context of siblings.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

search_fhirSearch FHIR resourcesA
Read-only

Search resources of a given type (GET /{resourceType}?...). Search parameters are passed through to the server as-is, so chained parameters, _has, _include, _revinclude, _sort, _total etc. all work. To keep responses small, prefer _elements (comma-separated field list) or _summary=true, and page with _count plus the returned hasNextPage flag (use params like _count/_offset or the server's paging links).

ParametersJSON Schema
NameRequiredDescriptionDefault
countNoResults per page (default 20, capped at 50)
paramsNoSearch parameters as key-value pairs, e.g. {"name": "山田", "_elements": "id,name,birthDate"}. Repeat-style OR values can be comma-separated per FHIR search rules.
resourceTypeYesFHIR resource type to search, e.g. Patient, Observation, Condition

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate readOnlyHint=true, so the tool is safe for reads. The description adds valuable behavioral context: HTTP GET method, parameter passthrough, pagination behavior, and response size control. No contradictions.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences with zero waste. The first sentence states the core action and HTTP method, the second provides crucial usage tips. Information is front-loaded and every sentence adds value.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema, but description explains the pagination response (hasNextPage flag). For a search tool with moderate complexity, it covers essential aspects: parameters, pagination, response size. Could mention more about return format but is sufficient.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema covers all 3 parameters with descriptions. The description adds extra meaning: params can include FHIR chaining, _include, _revinclude, and mentions _elements, _summary, _count which are not in schema but are related. Adds value beyond schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it searches resources of a given type via GET, and the title 'Search FHIR resources' reinforces this. It distinguishes from siblings like read_fhir (single resource retrieval) and patient_everything (specific patient bundle).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit guidance on when to use and how: pass parameters as-is, use _elements/_summary for small responses, paginate with _count and hasNextPage flag. It doesn't explicitly state when not to use but siblings imply alternatives.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

validate_fhirValidate a FHIR resourceA
Read-only

Validate a resource against the server's profiles without saving it (POST /{resourceType}/$validate). Use this before create_fhir/update_fhir to catch structural or terminology errors early. The resource JSON must include resourceType.

ParametersJSON Schema
NameRequiredDescriptionDefault
resourceYesThe FHIR resource to validate (JSON object including resourceType)

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Description confirms the operation is read-only (no save), aligning with readOnlyHint annotation. It adds behavioral context about the endpoint and required structure (resourceType), surpassing annotation detail.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two concise sentences, front-loaded with purpose and endpoint. No redundant or filler content.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Lacks description of the return value (e.g., OperationOutcome). While sufficient given no output schema, adding expected response type would improve completeness.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 100% schema coverage, schema already defines the param. Description adds critical constraint that resource must include resourceType, which is not in schema description, enhancing clarity.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool validates a FHIR resource against server profiles without saving, using a specific HTTP method and endpoint. It distinguishes from sibling tools like search or read by focusing on validation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly advises using this tool before create_fhir or update_fhir to catch errors early, providing clear context for when to use it over alternatives.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.

  1. 6 tool updatesv0.1.0
    • First observedget_capabilities
    • First observedget_history
    • First observedpatient_everything
    • First observedread_fhir
    • First observedsearch_fhir
    • First observedvalidate_fhir

TDQS

A4.2/5.0
Disambiguation5/5

Each tool targets a distinct FHIR operation: server metadata, searching, reading, patient compartment, history, and validation. No overlaps are apparent.

Naming Consistency4/5

Most tool names follow a verb_noun pattern (e.g., get_capabilities, search_fhir), except patient_everything which uses a noun_verb form. The inconsistency is minor and does not hinder understanding.

Tool Count5/5

Six tools is appropriate for a FHIR MCP server covering essential interactions: discovery, search, read, patient compartment, history, and validation. The scope is well-balanced.

Completeness2/5

The toolset lacks create, update, and delete operations, which are core to resource lifecycle management. The validate_fhir tool even references create_fhir/update_fhir as prerequisites, but they are missing.

Maintenance

ActivitySlowing
ResponsivenessSyncing

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

Related MCP Servers

  • -
    license
    Not graded
    quality
    Not graded
    maintenance
    Enables seamless integration with FHIR APIs for healthcare applications, allowing users to search, retrieve, create, update, and analyze clinical information through natural language interactions. Supports SMART-on-FHIR authentication and works with various healthcare systems like EPIC and HAPI FHIR servers.
    -
  • 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
    -
  • F
    license
    Not graded
    quality
    D
    maintenance
    Provides access to Medplum FHIR healthcare data, enabling Claude and other MCP clients to read, search, and query FHIR resources from one or more Medplum environments.
    16
    -

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/ysnr-dev/fhir-mcp-server'

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