Drug Prices について
Drug Prices は、米国の薬局の仕入れ価格や Medicare Part B の支払上限、340B データを調べる医療研究者・分析担当者向けの MCP サーバーです。NADAC と ASP を別の基準として扱い、データがない場合はその理由も示します。
主な機能
- 01NADAC の仕入れ価格検索
- 02週次 NADAC 価格履歴の確認
- 03Medicare Part B の ASP 上限検索
- 04利用可能な薬価基準の比較
- 05340B 事業体と薬局の検索
活用シーン
- 01薬局の医薬品仕入れコストの確認
- 02医薬品の Part B 支払上限の確認
- 03日付と単位を踏まえた価格基準の比較
- 04参加する 340B 拠点と薬局の関連付けの確認
MCP 対応
Pipeworx のエンドポイントを通じて、薬価と 340B の検索ツールを MCP クライアントに提供します。README にはサーバーの接続先と利用可能なツールも記載されています。
設定
リモートサーバーはインストール不要です。クライアントを選んで設定をコピーするか、ワンクリックで導入できます。
https://gateway.pipeworx.io/drug-prices/mcpclaude mcp add --transport http pipeworx-io-drug-prices https://gateway.pipeworx.io/drug-prices/mcp{"mcpServers":{"pipeworx-io-drug-prices":{"type":"http","url":"https://gateway.pipeworx.io/drug-prices/mcp"}}}Cursor で開く{"servers":{"pipeworx-io-drug-prices":{"type":"http","url":"https://gateway.pipeworx.io/drug-prices/mcp"}}}VS Code で開く{"mcpServers":{"pipeworx-io-drug-prices":{"type":"http","url":"https://gateway.pipeworx.io/drug-prices/mcp"}}}{"mcpServers":{"pipeworx-io-drug-prices":{"serverUrl":"https://gateway.pipeworx.io/drug-prices/mcp"}}}コマンドはターミナルで実行し、JSON は各クライアントの MCP 設定に貼り付けて再起動します。認可が必要なサーバーは初回接続時にログインを求めます。
ツール
詳細
drug-prices
米国の医薬品価格ベンチマーク:薬局が医薬品の仕入れに支払う金額と、医療提供者が投与する医薬品について Medicare Part B が払い出す金額です。キーは不要です。
Pipeworx の一部です。AI エージェントを1878以上のライブデータソースに接続する MCP ゲートウェイです。これは独立した非公式の統合であり、上流プロバイダーとは提携関係になく、承認も公開も受けていません。
この2つの数値は日常的に混同されていますが、このパックの主な役割は両者を区別することです。
| NADAC | ASP payment limit | |
|---|---|---|
| わかること | 小売薬局が卸売業者に支払う金額 | Medicare が診療所に支払う金額 |
| 更新頻度 | 毎週 | 四半期ごと |
| キー | NDC | HCPCS(Jコード) |
| 代表的な医薬品 | ジェネリック錠剤、小売製品 | がん治療薬、生物製剤、点滴薬、ワクチン |
| データソース | data.medicaid.gov 経由の CMS | CMS ASP Pricing Files(ZIP) |
ジェネリック錠剤には NADAC があり、ASP はありません。点滴投与のがん治療薬には ASP があり、通常、小売 NADAC はありません。drug_price_compare は、存在するベンチマークを返し、もう一方が見つからない理由を示します。空の結果は返しません。
ツール
nadac_price(drug | ndc, as_of?, limit?)— 現在の単位あたり仕入れコストnadac_history(ndc, weeks?)— 週ごとの価格推移と変化率asp_payment_limit(hcpcs | drug, quarter?, limit?)— 投与単位あたりの Part B 上限額drug_price_compare(drug, ndc?)— 両方のベンチマークを対象期間とともに並べて表示
データ処理
NADAC はライブで読み取ります。data.medicaid.gov は実際のクエリ API(フィルター、並べ替え、ページネーション)を公開しており、データセットには約20か月分のデータが含まれているため、ミラーリングは不要です。ASP にはAPI がありません。CMS は四半期ごとに ZIP ファイルを1つ公開しているため、scripts/ingest-asp-payment-limits.mjs で asp_payment_limits に取り込み、Supabase から読み取ります。
node scripts/ingest-asp-payment-limits.mjs # current quarter
node scripts/ingest-asp-payment-limits.mjs --back=5 # backfill
落とし穴
これらはすべてパックの構築中に実際に発生し、エラーではなく、自信に満ちた誤答をもたらしました。
NADAC の最新週のファイルは、通常、週次ファイルではなく訂正ファイルです。 NADAC は完全な週次ファイルに加え、同じ effective_date 列を共有する小さな臨時訂正ファイルを公開します。2026-08-28 の測定結果:2026-08-26 → 77 行、2026-08-19 → 58,163 行、2026-08-12 → 6 行です。わかりやすい設計、つまり max(effective_date) を取得してから絞り込む方法では、77 行のファイルが選ばれ、ほぼすべての薬剤で「価格が見つかりません」と報告されます。これは NADAC が対象としていない薬剤と区別がつきません。まず薬剤で絞り込み、次に一致した結果から最新の日付を取得してください。
データストア API は不明なパラメーターを黙って無視します。 ?sort=-effective_date は HTTP 200 を返しますが、行はソートされていません。?zzznonsense=x とバイト単位で同一です。ソートされるのは sorts[0][property] と sorts[0][order] の組み合わせだけです。ここでスペルを間違えても失敗せず、任意の週の価格が静かに返されます。
NADAC のデータセット ID は毎年 1 月に切り替わり、タイトルに含まれる年は対象期間を示すものではありません。 「NADAC … 2026」というデータセットには、2025-01-01 から 2026-08-26 までの有効日が含まれています。ID は呼び出し時にタイトルから解決し、最後に確認された ID をフォールバックとして使用するため、1 月になってもパックが機能しなくなることはありません。
NADAC には 2 種類の日付があります。 effective_date は価格が適用される週、as_of_date は CMS が公開した日付です。価格のキーには前者を使用し、両方を返します。
ASP 支払限度額のデータ時点は、その四半期とは異なります。 CMS ファイルには、「2026-07-01 適用のファイルは 「1Q26 ASP データに基づく」」と記載されています。有効な限度額はおよそ 2 四半期前の ASP データに基づくため、今週の NADAC と比較すると約 6 か月の開きがあります。両方の四半期を必ず返します。
ASP CSV は UTF-8 ではなく windows-1252 で、実際の値の中に 0xA0("1 million\xa0PFU")が含まれています。UTF-8 として読み込むと例外が発生します。さらに悪いことに、grep は不正なバイトに遭遇すると黙って処理を中断します。そのため、実際にはファイルに含まれている J9271 が、最初は欠落しているように見えました。
ASP CSV のヘッダーは 1 行目ではありません(その前に 9 行の注記があり、その数は四半期ごとに異なります)。また、内部のファイル名には四半期ごとのビルド日(…File 061626.csv)が含まれています。どちらもオフセットや固定のファイル名ではなく、パターンで照合します。CMS は ZIP ファイル名に -final-file サフィックスを付けるかどうかも一貫していないため、両方の表記を試します。
NADAC はブランド製品を有効成分名ではなく、ブランド名で記載します。 APIXABAN に一致する行は 0 件ですが、ELIQUIS には 204 件一致します。現在もブランド名で販売されている薬剤を一般名で検索すると、確信を持って空の結果を返します。また、「診療所で投与される薬剤に違いない」というもっともらしい説明は、このケースでは誤りです。結果が空の場合の注記では、どちらか一方と断定せず、可能性の高い順に両方を提示します。
NDC には 3 種類の形式があります — ハイフン区切りの 5-4-2 桁、11 桁、先頭のゼロが欠けた 10 桁の形式です。これらを文字列として相互に置き換えることはできません。すべて正規の 11 桁形式に正規化します。
payment_limit は dosage の単位あたりの値です。 J9271 は 1 MG あたり 60.645 ドルなので、200 MG の投与では 200 倍になります。単位を付けずに限度額を返すと 200 倍の誤りを招くため、この 2 つは必ず一緒に返します。
drug_price_compare は、2 つのベンチマーク間の計算を意図的に行いません。 NADAC は価格単位(EA/ML/GM)あたり、ASP は HCPCS の投与量あたりで、分母が異なり、測定時期も数か月離れています。一方を他方で割ると、確信に満ちた、意味のない「利益率」が算出されます。
340B 対象医療機関
b340_covered_entities と b340_contract_pharmacies は、HRSA OPAIS のミラーを読み取ります。2026-09-07 のエクスポート時点で、対象医療機関の登録は94,363件(現在参加中は64,413件)、契約薬局とのリンクは398,441件です。
340B ID は組織単位ではなく、サイトごとに付与されます。1つの医療システムが複数のIDを持つことがあり、parent_id340b は子サイトと登録済みの親病院を結び付けます。登録リストのおよそ3分の1は終了済みの登録のため、指定がない限り、両方のツールで除外されます。「一致なし」と回答する場合は、その旨を明示するため、対象機関がかつて存在しなかったかのような誤解を招きません。
type には "hospital"、"health center"、"Ryan White"、"critical access" などの一般的な語句のほか、HRSA の23種類のコードも指定できます。state には "TX" だけでなく "Texas" も指定できます。認識できない値は、無視して全件をフィルターなしで返すのではなく、有効な値の一覧とともに拒否されます。フィルターを無視すると、正常な200応答とともにフィルターなしの結果一式が返り、正しい回答に見えてしまうためです。
連絡担当者の情報はありません。 エクスポートには authorizingOfficial と primaryContact が含まれており、直通電話番号付きの個人名が94,363件あります。これらはどちらも取り込まれておらず、該当する列もないため、どのクエリでも取得できません。移行時のヘッダーを参照してください。
最新の状態を保つ方法 — 人がボタンをクリックします
ここの340Bデータは、意図的に、人の手でおよそ月に1回更新されます。
.github/workflows/340b-refresh-reminder.ymlは毎月1日に実行され、データの読み込みが25日間行われておらず、同様の依頼がすでに未完了の場合に限り、フリートタスクを登録します。- 誰かが https://340bopais.hrsa.gov/Reports で Covered Entity Daily Export (JSON) をクリックし、
bash scripts/340b-drop.sh ~/Downloads/340B_CoveredEntityJson_Daily_*.zipを実行します。 .github/workflows/340b-ingest.ymlが解析と読み込みを行い、タスクを完了します。
as_of は読み込み日ではなく、エクスポートのファイル名から取得されるため、ダウンロードフォルダーに1週間置かれていたファイルでデータの新しさを誤って示すことはありません。ローダーは、対象医療機関が50,000件未満の登録リストへの置き換えを拒否するため、ダウンロードが途中で切れていた場合にデータがひそかに減るのではなく、明確にエラーになります。すべての応答に as_of が含まれます。
自動化できない理由
fleet #618 で指定され、#633 で調査しましたが、私たちが実行するものではエクスポートを取得できません。 2026-09-01(fleet #804)および2026-09-07(fleet #633)に再確認済みです。現在も変わりありません。
HRSA OPAIS(340bopais.hrsa.gov)は、ここで最初に記録したようなクライアント側レンダリングではなく、Blazor Server です。/Reports は _framework/blazor.web.js(.NET 8 以降の Blazor Web App)を配信し、SignalR 回路のエンドポイントは稼働しています。
以前このファイルで証拠として引用していた 411 は、何も証明しません。そのプローブを繰り返さないでください。 ホスト上のどのパスに対しても、本文なしの POST を送ると、存在しないパスも含めてエッジから 411 Length Required が返ります。空の本文と Content-Length: 0 を送ると、各パスの違いが明確になります(2026-09-01 に測定)。
| パス | 本文なしの POST | POST -d '' |
|---|---|---|
/_blazor/negotiate?negotiateVersion=1 | 411 | 200 {"negotiateVersion":1,"connectionId":"…","connectionToken":"…","availableTransports":[WebSockets, ServerSentEvents, LongPolling]} |
/DXXRDV | 411 | 404、0 バイト |
/nonexistentpath123 | 411 | 404、0 バイト |
/DXXRDV を挙げる価値があるのは、/Reports が DevExpress Web Document Viewer のスクリプトを読み込み、そのコントロールは通常、このパスに HTTP コントローラーをマウントするためです。OPAIS はまだ公開していませんが、いかにも使えそうな REST の入口です。
再現できるリクエストはありません。 ブラウザーで /Reports を読み込み、ネットワークログを消去して Covered Entity Daily Export (JSON) をクリックしても、記録される HTTP リクエストはゼロです。すべての通信、および _blazor に絞った場合のどちらでも同じです。ファイルはページ読み込み時からすでに開いていた WebSocket 経由で返されます。WebSocket フレームは HTTP リクエストではありません。HRSA の FAQ にも同じことが記載されており、直接ダウンロードできる URL はなく、「ポストバックとボタンのクリックは、現在のセッションおよびビューステートのコンテキストで行う必要があります」。
訂正、2026-09-07 に測定(fleet #633、Alaric):障害の原因は WebSocket ではなく、STATEFUL CIRCUIT です。 このファイルでは以前、WebSocket トランスポートが「curl、Worker、cron のいずれにも呼び出し先がない」理由だと説明していました。この理由は誤りです。以前の 411 と同じ誤りで、次に再調査する人が 1 つのコマンドで否定できる症状を理由として挙げていました。negotiate が通知するのは 1 つではなく、3 つのトランスポートです。WebSockets、ServerSentEvents、LongPolling です。LongPolling は通常の HTTP POST/GET なので、Worker からこの回路を操作できます。使わない理由は、接続後に呼び出し元が行う必要のある操作です。Blazor コンポーネントのハンドシェイクを再現し、バイナリのレンダーバッチからボタンのコンポーネント ID を読み取り、ボタンに対して合成 UI イベントを送信し、回路フレームからストリーミングファイルを再構成する必要があります。これはステートフルな UI セッションのエミュレーションであり、コンポーネントが変更されると、エラーを返さずにエンティティの一覧が縮小する形で気づかないうちに破綻します。結論は変わりませんが、根拠は適切なものに改められました。これはトランスポートが原因で使えないのではなく、稼働中の UI をスクレイピングする必要があるため使えないのです。
ミラーもありません。 2026-09-01 に再確認しました。HRSA Data Warehouse のダウンロードカタログ(一覧 452 KB、データセットラベル 125 件)に 340b の文字列は一度も登場しません。healthdata.gov の Socrata カタログで ?q=340B を検索すると resultSetSize: 1 と返りますが、その唯一のヒットはデータセットではなく、data.hrsa.gov (HRSA Data Warehouse) のリンクエントリーです。catalog.data.gov/api/3/action/package_search は API 自体が 404 を返し、data.hrsa.gov/api/views.json と、分かりやすい一括ダウンロードパスも 404 です。
そのため、人間が介在する方法を採用していましたが、現在はそれが実装されています(Bruce が毎月クリックすることに同意、2026-09-07)。340B の登録は四半期ごとに変更されます。エクスポートが夜間に行われるのは、毎晩再生成されるためであり、名簿が頻繁に変わるためではありません。そのため毎月のクリックで実際のテーブルを取得でき、信頼できる as_of を記録できます。また、次のコンポーネント変更で気づかないうちに破綻する、ステートフルアプリのスクレイパーも必要ありません。上記の「最新状態を保つ仕組み」を参照してください。
クイックスタート
MCP クライアント(Claude Desktop、Cursor、Windsurf など)に追加します。
{
"mcpServers": {
"drug-prices": {
"url": "https://gateway.pipeworx.io/drug-prices/mcp"
}
}
}
このエンドポイントが実際に提供するもの
https://gateway.pipeworx.io/drug-prices/mcp の tools/list は、上の表にあるツールに加えて、Pipeworx の共通メタツールである ask_pipeworx、discover_tools、search_within、remember/recall など、ゲートウェイ全体で使えるツールも返します。そのため、表示されるツール数はこの表より多くなります。現在、単一パックのエンドポイントには、パック固有のツールとともに約 30 個の共通ツールが一覧表示されます。接続時の initialize レスポンスに正確なスコープが示されており、その日の状況を確認するための確かな情報源です。
これは意図的な仕様であり、偶然の多重化ではありません。メタツールを使うと、このパックでは扱えない質問にも、カタログ全体を横断してルーティングする ask_pipeworx を介して回答できます。そのため、2 つ目の MCP サーバーを追加する必要はありません。現在、メタツールを使わずにパックのエンドポイントだけを接続する方法はありません。追加のスキーマによるコンテキスト消費がルーティングの利点を上回る場合は、複数のパックエンドポイントではなく、フルゲートウェイに一度だけ接続してください。
または、Pipeworx のフルゲートウェイに接続すると、このパックのツールだけでなく、すべてのパックのツールを直接一覧表示できます。
{
"mcpServers": {
"pipeworx": {
"url": "https://gateway.pipeworx.io/mcp"
}
}
}
どちらの URL も、同じゲートウェイと同じ 1878 以上のデータソースに接続します。違いは、どのパックのツールが直接一覧表示されるかだけです。どちらからでも ask_pipeworx を使って、すべてのツールを利用できます。
MCP クライアントがなくても HTTP で呼び出せます
curl -X POST https://gateway.pipeworx.io/v1/tools/nadac_price \
-H 'Content-Type: application/json' \
-d '{"drug":"atorvastatin 20 mg"}'
最初の呼び出しにはアカウントは必要ありません。ツールを確認するには、GET https://gateway.pipeworx.io/v1/tools/nadac_price を使います。ツールを検索するには、{"query":"..."} を指定して POST https://gateway.pipeworx.io/v1/tools/search_packs を使います。
スタンドアロン(ゲートウェイアカウント不要)
このパッケージは、ローカルの stdio MCP サーバーとしても実行できます。Pipeworx アカウントも、ゲートウェイへの往復通信も必要ありません。
{
"mcpServers": {
"drug-prices": {
"command": "npx",
"args": ["-y", "@pipeworx/mcp-drug-prices"]
}
}
}
または、直接実行して起動を確認できます。
npx -y @pipeworx/mcp-drug-prices
stdin/stdout 経由で MCP と通信し、initialize/tools/list/tools/call に対して、このパックのツールのみを返します。上記のゲートウェイ接続で追加される共通メタツールは含まれません。同じソース、同じツールで、ask_pipeworx によるルーティングはありません。
ask_pipeworx を使う
ツールを直接呼び出す代わりに、自然な英語で質問できます。これは上記のパックエンドポイントとフルゲートウェイの両方で利用できます。
ask_pipeworx({ question: "your question about Drug Prices data" })
ゲートウェイが適切なツールを選び、引数を自動的に設定します。
詳細
ライセンス
MIT
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。