@pipeworx/oh-medical-exclusions
Connect: https://pipeworx.io/mcp — every tool in the catalog, including @pipeworx/oh-medical-exclusions’s. Install: one-click buttons
Connect to just the @pipeworx/oh-medical-exclusions pack
https://gateway.pipeworx.io/oh-medical-exclusions/mcp — only @pipeworx/oh-medical-exclusions’s own tools, nothing else in the catalog.
No MCP client? Skip the connection: POST https://gateway.pipeworx.io/v1/tools/search_packs {"query":"..."} to find a tool below, GET /v1/tools/<name> for its schema, POST the same URL with arguments for the data — see For AI agents.
Tools: 2
Ohio Department of Medicaid (ODM) Provider Exclusion & Suspension List
screening — check a provider by name, NPI, or ODM Provider ID against the
~2,122-row list of individuals and organizations excluded or suspended
from Ohio’s Medicaid program, the state-level counterpart to the federal
HHS OIG LEIE (leie pack) and the sibling of ny-omig-exclusions (New
York), ca-medical-exclusions (California), tx-medical-exclusions
(Texas), fl-medical-exclusions (Florida), pa-medical-exclusions
(Pennsylvania) and ga-medical-exclusions (Georgia).
Tools
oh_medical_check_exclusion(name?, npi?, provider_id?, limit?)— screens a provider against the ODM exclusion/suspension list. An NPI or Provider ID match is an identification (both are exact identifiers, and either can be a comma-joined list on one row when a provider is excluded under multiple registrations); a name match — even an exact one — is a candidate lead only, since this list carries no date of birth. Every match carries ODM’s ownstatusand acurrently_excludedflag derived from it.oh_medical_exclusion_coverage()— total rows (individuals plus organizations), how many are currently excluded/suspended vs. status-unknown, how many carry an NPI, and the oldest/newest exclusion effective date. Passyearorstart_date/end_dateto instead count exclusions whose effective date falls in that range, over the whole list.
Auth
Keyless.
Data sources
- Ohio Department of Medicaid (ODM), Provider Exclusion & Suspension List — the state’s published roster of individuals and organizations excluded from, or currently suspended from, Ohio’s Medicaid program, published at https://medicaid.ohio.gov/resources-for-providers/enrollment-and-support/provider-enrollment/provider-exclusion-and-suspension-list.
The listing page 404s for a plain curl — that is a UA block, not a dead page
Verified live 2026-10-17: a request with no browser-shaped User-Agent
gets a stale CloudFront 404 fallback from Ohio’s CDN; the identical
request with a browser-shaped UA string returns 200. This is the
UA-sniffing class the “public data is public data” ruling already covers
— not a login wall, not a CAPTCHA. scripts/bake-index.mjs still
identifies the pack honestly (its UA string names it and carries a
contact URL); the string is shaped to get past a bot filter, not to
impersonate a browser. The asset CDN that actually serves the .xlsx does
not need this — only the page that names its current URL does.
The download link is NOT stable — resolved fresh every bake
The linked .xlsx lives on Ohio’s asset CDN
(dam.assets.ohio.gov/raw/upload/medicaid.ohio.gov/...) and its FILENAME
embeds the publication date (e.g.
ExclusionSuspensionList_10_15_2026-3.xlsx). scripts/bake-index.mjs
resolves the current link from the listing page every run — the same
“resolve from the listing page, never guess the filename” discipline
ga-medical-exclusions and scripts/ingest-dmepos.mjs use for their own
unstable upstream filenames.
Why this is baked, not a live proxy
Per root CLAUDE.md’s standing rule for a table this size, the full list
(2,122 rows at capture time) is baked into src/oh-odm-index-data.ts,
registered in workers/gateway/src/pack-baked-indexes.json, uploaded to
KV at deploy, and injected into every call as args._bakedIndex — never a
static module-scope import (fleet #2754). A missing or malformed
injection throws loudly rather than answering “not found” — see
src/index.test.ts.
No external XLSX library — hand-rolled, same discipline as the sibling packs
Reuses ga-medical-exclusions/scripts/bake-index.mjs’s pure-Node zip
reader (itself from scripts/ingest-dmepos.mjs: Node’s built-in
zlib.inflateRawSync over a hand-walked central directory — no unzip
CLI, no npm package). This workbook needs sheets resolved by name
(“Individuals” is rId2/worksheets/sheet2.xml, “Organizations” is
rId3/worksheets/sheet3.xml — not the first sheet, which is
“Instructions” prose), unlike ga-medical-exclusions, which only needed
the workbook’s first sheet.
Two sheets, one unified row shape
ODM publishes this as Individuals (1,867 rows at capture: name, DOB,
NPI, Provider ID, Status, Action Date, Date Added, Provider Type) and
Organizations (255 rows: NPI, organization name, address, Provider ID,
Status, Action Date, Date Added, Provider Type). Both are baked into one
row shape tagged record_type: 'individual' | 'organization'.
Dates are Excel serials, except two rows that are plain text
Verified directly against all ~2,122 rows: Action Date and Date Added are
untyped numeric cells (Excel date serials) for all but 2 Individuals rows,
where ODM’s own data entry put literal "9/24/2025" text into the cell
instead. bake-index.mjs decodes both shapes — by cell TYPE here (string
vs. numeric), not magnitude, since there is no 8-digit-YYYYMMDD ambiguity
in this file the way there was in ga-medical-exclusions’s SANCDATE
column.
Action Date vs. Date Added — same trap as every precedent pack
Verified directly: of the rows carrying both dates, 1,035/1,064 (Individuals) and 123/133 (Organizations) have different values. Action Date is when the exclusion/suspension took effect; Date Added is when ODM added the row to this published file. This pack counts by Action Date only, never Date Added.
NPI, Provider ID and Provider Type can be comma-joined lists
31 Individuals rows and 11 Organizations rows carry more than one NPI on a
single row (one person/entity excluded under multiple Medicaid
registrations), e.g. "1447317433, 1598934424" with a matching Provider
ID pair "2744918, 2798898". Matching splits on comma and compares each
fragment, so a query for either value finds the row.
Status has whitespace/case/typo variants
Besides clean “Excluded”/“Suspended”, the live file has " Excluded"
(leading space), "Excluded " (trailing space), "suspended"
(lowercase), a single "susepnded" (typo), a handful of "Terminated",
and a few blank cells. This pack trims+lowercases for its own
active/inactive classification (currently_excluded: true only for a
recognized Excluded/Suspended value; everything else —
including the typo and “Terminated” — gets currently_excluded: null and
status_unknown: true) but serves the status text as published, trimmed
only, never “corrected.”
No home address, no date of birth
The Individuals sheet carries a date-of-birth column and the
Organizations sheet carries a full street address (Address 1/2, City,
State, Zip). Neither is carried into this pack — the task’s house rule is
to serve the same fields the six precedent state packs serve and add no
new personal identifier or address beyond them; none of those packs serve
a street address or a date of birth. bake-index.mjs reads both columns
only to parse past them.
Matching
An npi query matches only exact 10-digit numeric NPI values, checked
against every comma-separated fragment on a row. A provider_id query
matches ODM’s own Provider ID, leading-zero-tolerant, also checked against
every fragment. Name queries match against the provider’s assembled
individual name or organization name, any word order,
case/punctuation-insensitive.
Reachability
Verified live 2026-10-17: the listing page (with a browser-shaped UA)
resolves a current download link, and that link returns 200 with an
Excel 2007+ file, 2,122 data rows across both sheets.
Tools
- oh_medical_check_exclusion — Is this healthcare provider excluded from, or suspended from, the Ohio Medicaid program? Screens a person or organization name, an NPI, and/or an ODM Provider ID against the Ohio Department of Medicai
- oh_medical_exclusion_coverage — What the Ohio ODM exclusion/suspension data covers and how current it is: total rows (individuals plus organizations), how many are currently excluded/suspended vs. status-unknown, how many carry an N
Tools
oh_medical_check_exclusion— Is this healthcare provider excluded from, or suspended from, the Ohio Medicaid program? Screens a person or organization name, an NPI, and/or an ODM Provider ID against the Ohio Department of Medicaioh_medical_exclusion_coverage— What the Ohio ODM exclusion/suspension data covers and how current it is: total rows (individuals plus organizations), how many are currently excluded/suspended vs. status-unknown, how many carry an N